Bug Summary

File:kern/subr_disk.c
Warning:line 1632, column 10
Access to field 'dv_class' results in a dereference of a null pointer (loaded from variable 'rootdv')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name subr_disk.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/kern/subr_disk.c
1/* $OpenBSD: subr_disk.c,v 1.272 2023/11/15 20:23:19 kn Exp $ */
2/* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */
3
4/*
5 * Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
6 * Copyright (c) 1982, 1986, 1988, 1993
7 * The Regents of the University of California. All rights reserved.
8 * (c) UNIX System Laboratories, Inc.
9 * All or some portions of this file are derived from material licensed
10 * to the University of California by American Telephone and Telegraph
11 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
12 * the permission of UNIX System Laboratories, Inc.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/malloc.h>
44#include <sys/fcntl.h>
45#include <sys/buf.h>
46#include <sys/stat.h>
47#include <sys/syslog.h>
48#include <sys/device.h>
49#include <sys/time.h>
50#include <sys/disklabel.h>
51#include <sys/conf.h>
52#include <sys/disk.h>
53#include <sys/reboot.h>
54#include <sys/dkio.h>
55#include <sys/vnode.h>
56#include <sys/task.h>
57#include <sys/stdint.h>
58
59#include <sys/socket.h>
60
61#include <net/if.h>
62
63#include <dev/cons.h>
64
65#include <lib/libz/zlib.h>
66
67#include "softraid.h"
68
69#ifdef DEBUG
70#define DPRINTF(x...) printf(x)
71#else
72#define DPRINTF(x...)
73#endif
74
75/*
76 * A global list of all disks attached to the system. May grow or
77 * shrink over time.
78 */
79struct disklist_head disklist; /* TAILQ_HEAD */
80int disk_count; /* number of drives in global disklist */
81int disk_change; /* set if a disk has been attached/detached
82 * since last we looked at this variable. This
83 * is reset by hw_sysctl()
84 */
85
86#define DUID_SIZE8 8
87
88u_char bootduid[DUID_SIZE8]; /* DUID of boot disk. */
89u_char rootduid[DUID_SIZE8]; /* DUID of root disk. */
90
91struct device *rootdv;
92
93/* softraid callback, do not use! */
94void (*softraid_disk_attach)(struct disk *, int);
95
96void sr_map_root(void);
97
98struct disk_attach_task {
99 struct task task;
100 struct disk *dk;
101};
102
103void disk_attach_callback(void *);
104
105int spoofgpt(struct buf *, void (*)(struct buf *), const uint8_t *,
106 struct disklabel *, daddr_t *);
107void spoofmbr(struct buf *, void (*)(struct buf *), const uint8_t *,
108 struct disklabel *, daddr_t *);
109void spooffat(const uint8_t *, struct disklabel *, daddr_t *);
110
111int gpt_chk_mbr(struct dos_partition *, uint64_t);
112int gpt_get_hdr(struct buf *, void (*)(struct buf *), struct disklabel *,
113 uint64_t, struct gpt_header *);
114int gpt_get_parts(struct buf *, void (*)(struct buf *),
115 struct disklabel *, const struct gpt_header *, struct gpt_partition **);
116int gpt_get_fstype(const struct uuid *);
117int mbr_get_fstype(const uint8_t);
118
119int duid_equal(u_char *, u_char *);
120
121/*
122 * Compute checksum for disk label.
123 */
124u_int
125dkcksum(struct disklabel *lp)
126{
127 u_int16_t *start, *end;
128 u_int16_t sum = 0;
129
130 start = (u_int16_t *)lp;
131 end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
132 while (start < end)
133 sum ^= *start++;
134 return (sum);
135}
136
137int
138initdisklabel(struct disklabel *lp)
139{
140 int i;
141
142 /* minimal requirements for archetypal disk label */
143 if (lp->d_secsize < DEV_BSIZE(1 << 9))
144 lp->d_secsize = DEV_BSIZE(1 << 9);
145 if (DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
== 0)
146 DL_SETDSIZE(lp, MAXDISKSIZE)do { u_int64_t __x = (0x7fffffffffffLL); (lp)->d_secperunith
= __x >> 32; (lp)->d_secperunit = __x; } while (0)
;
147 if (lp->d_secpercyl == 0)
148 return (ERANGE34);
149 lp->d_npartitions = MAXPARTITIONS16;
150 for (i = 0; i < RAW_PART2; i++) {
151 DL_SETPSIZE(&lp->d_partitions[i], 0)do { u_int64_t __x = (0); (&lp->d_partitions[i])->p_sizeh
= __x >> 32; (&lp->d_partitions[i])->p_size =
__x; } while (0)
;
152 DL_SETPOFFSET(&lp->d_partitions[i], 0)do { u_int64_t __x = (0); (&lp->d_partitions[i])->p_offseth
= __x >> 32; (&lp->d_partitions[i])->p_offset
= __x; } while (0)
;
153 }
154 if (DL_GETPSIZE(&lp->d_partitions[RAW_PART])(((u_int64_t)(&lp->d_partitions[2])->p_sizeh <<
32) + (&lp->d_partitions[2])->p_size)
== 0)
155 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp))do { u_int64_t __x = ((((u_int64_t)(lp)->d_secperunith <<
32) + (lp)->d_secperunit)); (&lp->d_partitions[2])
->p_sizeh = __x >> 32; (&lp->d_partitions[2])
->p_size = __x; } while (0)
;
156 DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0)do { u_int64_t __x = (0); (&lp->d_partitions[2])->p_offseth
= __x >> 32; (&lp->d_partitions[2])->p_offset
= __x; } while (0)
;
157 DL_SETBSTART(lp, 0)do { u_int64_t __x = (0); (lp)->d_bstarth = __x >> 32
; (lp)->d_bstart = __x; } while (0)
;
158 DL_SETBEND(lp, DL_GETDSIZE(lp))do { u_int64_t __x = ((((u_int64_t)(lp)->d_secperunith <<
32) + (lp)->d_secperunit)); (lp)->d_bendh = __x >>
32; (lp)->d_bend = __x; } while (0)
;
159 lp->d_version = 1;
160 return (0);
161}
162
163/*
164 * Check an incoming block to make sure it is a disklabel, convert it to
165 * a newer version if needed, etc etc.
166 */
167int
168checkdisklabel(dev_t dev, void *rlp, struct disklabel *lp, u_int64_t boundstart,
169 u_int64_t boundend)
170{
171 struct disklabel *dlp = rlp;
172 struct __partitionv0 *v0pp;
173 struct partition *pp;
174 const char *blkname;
175 u_int64_t disksize;
176 int error = 0;
177 int i;
178
179 if (dlp->d_magic != DISKMAGIC((u_int32_t)0x82564557) || dlp->d_magic2 != DISKMAGIC((u_int32_t)0x82564557))
180 error = ENOENT2; /* no disk label */
181 else if (dlp->d_npartitions > MAXPARTITIONS16)
182 error = E2BIG7; /* too many partitions */
183 else if (dlp->d_secpercyl == 0)
184 error = EINVAL22; /* invalid label */
185 else if (dlp->d_secsize == 0)
186 error = ENOSPC28; /* disk too small */
187 else if (dkcksum(dlp) != 0)
188 error = EINVAL22; /* incorrect checksum */
189
190 if (error) {
191 u_int16_t *start, *end, sum = 0;
192
193 /* If it is byte-swapped, attempt to convert it */
194 if (swap32(dlp->d_magic)(__uint32_t)(__builtin_constant_p(dlp->d_magic) ? (__uint32_t
)(((__uint32_t)(dlp->d_magic) & 0xff) << 24 | ((
__uint32_t)(dlp->d_magic) & 0xff00) << 8 | ((__uint32_t
)(dlp->d_magic) & 0xff0000) >> 8 | ((__uint32_t)
(dlp->d_magic) & 0xff000000) >> 24) : __swap32md
(dlp->d_magic))
!= DISKMAGIC((u_int32_t)0x82564557) ||
195 swap32(dlp->d_magic2)(__uint32_t)(__builtin_constant_p(dlp->d_magic2) ? (__uint32_t
)(((__uint32_t)(dlp->d_magic2) & 0xff) << 24 | (
(__uint32_t)(dlp->d_magic2) & 0xff00) << 8 | ((__uint32_t
)(dlp->d_magic2) & 0xff0000) >> 8 | ((__uint32_t
)(dlp->d_magic2) & 0xff000000) >> 24) : __swap32md
(dlp->d_magic2))
!= DISKMAGIC((u_int32_t)0x82564557) ||
196 swap16(dlp->d_npartitions)(__uint16_t)(__builtin_constant_p(dlp->d_npartitions) ? (__uint16_t
)(((__uint16_t)(dlp->d_npartitions) & 0xffU) << 8
| ((__uint16_t)(dlp->d_npartitions) & 0xff00U) >>
8) : __swap16md(dlp->d_npartitions))
> MAXPARTITIONS16)
197 return (error);
198
199 /*
200 * Need a byte-swap aware dkcksum variant
201 * inlined, because dkcksum uses a sub-field
202 */
203 start = (u_int16_t *)dlp;
204 end = (u_int16_t *)&dlp->d_partitions[
205 swap16(dlp->d_npartitions)(__uint16_t)(__builtin_constant_p(dlp->d_npartitions) ? (__uint16_t
)(((__uint16_t)(dlp->d_npartitions) & 0xffU) << 8
| ((__uint16_t)(dlp->d_npartitions) & 0xff00U) >>
8) : __swap16md(dlp->d_npartitions))
];
206 while (start < end)
207 sum ^= *start++;
208 if (sum != 0)
209 return (error);
210
211 dlp->d_magic = swap32(dlp->d_magic)(__uint32_t)(__builtin_constant_p(dlp->d_magic) ? (__uint32_t
)(((__uint32_t)(dlp->d_magic) & 0xff) << 24 | ((
__uint32_t)(dlp->d_magic) & 0xff00) << 8 | ((__uint32_t
)(dlp->d_magic) & 0xff0000) >> 8 | ((__uint32_t)
(dlp->d_magic) & 0xff000000) >> 24) : __swap32md
(dlp->d_magic))
;
212 dlp->d_type = swap16(dlp->d_type)(__uint16_t)(__builtin_constant_p(dlp->d_type) ? (__uint16_t
)(((__uint16_t)(dlp->d_type) & 0xffU) << 8 | ((__uint16_t
)(dlp->d_type) & 0xff00U) >> 8) : __swap16md(dlp
->d_type))
;
213
214 /* d_typename and d_packname are strings */
215
216 dlp->d_secsize = swap32(dlp->d_secsize)(__uint32_t)(__builtin_constant_p(dlp->d_secsize) ? (__uint32_t
)(((__uint32_t)(dlp->d_secsize) & 0xff) << 24 | (
(__uint32_t)(dlp->d_secsize) & 0xff00) << 8 | ((
__uint32_t)(dlp->d_secsize) & 0xff0000) >> 8 | (
(__uint32_t)(dlp->d_secsize) & 0xff000000) >> 24
) : __swap32md(dlp->d_secsize))
;
217 dlp->d_nsectors = swap32(dlp->d_nsectors)(__uint32_t)(__builtin_constant_p(dlp->d_nsectors) ? (__uint32_t
)(((__uint32_t)(dlp->d_nsectors) & 0xff) << 24 |
((__uint32_t)(dlp->d_nsectors) & 0xff00) << 8 |
((__uint32_t)(dlp->d_nsectors) & 0xff0000) >> 8
| ((__uint32_t)(dlp->d_nsectors) & 0xff000000) >>
24) : __swap32md(dlp->d_nsectors))
;
218 dlp->d_ntracks = swap32(dlp->d_ntracks)(__uint32_t)(__builtin_constant_p(dlp->d_ntracks) ? (__uint32_t
)(((__uint32_t)(dlp->d_ntracks) & 0xff) << 24 | (
(__uint32_t)(dlp->d_ntracks) & 0xff00) << 8 | ((
__uint32_t)(dlp->d_ntracks) & 0xff0000) >> 8 | (
(__uint32_t)(dlp->d_ntracks) & 0xff000000) >> 24
) : __swap32md(dlp->d_ntracks))
;
219 dlp->d_ncylinders = swap32(dlp->d_ncylinders)(__uint32_t)(__builtin_constant_p(dlp->d_ncylinders) ? (__uint32_t
)(((__uint32_t)(dlp->d_ncylinders) & 0xff) << 24
| ((__uint32_t)(dlp->d_ncylinders) & 0xff00) <<
8 | ((__uint32_t)(dlp->d_ncylinders) & 0xff0000) >>
8 | ((__uint32_t)(dlp->d_ncylinders) & 0xff000000) >>
24) : __swap32md(dlp->d_ncylinders))
;
220 dlp->d_secpercyl = swap32(dlp->d_secpercyl)(__uint32_t)(__builtin_constant_p(dlp->d_secpercyl) ? (__uint32_t
)(((__uint32_t)(dlp->d_secpercyl) & 0xff) << 24 |
((__uint32_t)(dlp->d_secpercyl) & 0xff00) << 8 |
((__uint32_t)(dlp->d_secpercyl) & 0xff0000) >> 8
| ((__uint32_t)(dlp->d_secpercyl) & 0xff000000) >>
24) : __swap32md(dlp->d_secpercyl))
;
221 dlp->d_secperunit = swap32(dlp->d_secperunit)(__uint32_t)(__builtin_constant_p(dlp->d_secperunit) ? (__uint32_t
)(((__uint32_t)(dlp->d_secperunit) & 0xff) << 24
| ((__uint32_t)(dlp->d_secperunit) & 0xff00) <<
8 | ((__uint32_t)(dlp->d_secperunit) & 0xff0000) >>
8 | ((__uint32_t)(dlp->d_secperunit) & 0xff000000) >>
24) : __swap32md(dlp->d_secperunit))
;
222
223 /* d_uid is a string */
224
225 dlp->d_acylinders = swap32(dlp->d_acylinders)(__uint32_t)(__builtin_constant_p(dlp->d_acylinders) ? (__uint32_t
)(((__uint32_t)(dlp->d_acylinders) & 0xff) << 24
| ((__uint32_t)(dlp->d_acylinders) & 0xff00) <<
8 | ((__uint32_t)(dlp->d_acylinders) & 0xff0000) >>
8 | ((__uint32_t)(dlp->d_acylinders) & 0xff000000) >>
24) : __swap32md(dlp->d_acylinders))
;
226
227 dlp->d_flags = swap32(dlp->d_flags)(__uint32_t)(__builtin_constant_p(dlp->d_flags) ? (__uint32_t
)(((__uint32_t)(dlp->d_flags) & 0xff) << 24 | ((
__uint32_t)(dlp->d_flags) & 0xff00) << 8 | ((__uint32_t
)(dlp->d_flags) & 0xff0000) >> 8 | ((__uint32_t)
(dlp->d_flags) & 0xff000000) >> 24) : __swap32md
(dlp->d_flags))
;
228
229 dlp->d_secperunith = swap16(dlp->d_secperunith)(__uint16_t)(__builtin_constant_p(dlp->d_secperunith) ? (__uint16_t
)(((__uint16_t)(dlp->d_secperunith) & 0xffU) << 8
| ((__uint16_t)(dlp->d_secperunith) & 0xff00U) >>
8) : __swap16md(dlp->d_secperunith))
;
230 dlp->d_version = swap16(dlp->d_version)(__uint16_t)(__builtin_constant_p(dlp->d_version) ? (__uint16_t
)(((__uint16_t)(dlp->d_version) & 0xffU) << 8 | (
(__uint16_t)(dlp->d_version) & 0xff00U) >> 8) : __swap16md
(dlp->d_version))
;
231
232 for (i = 0; i < NSPARE4; i++)
233 dlp->d_spare[i] = swap32(dlp->d_spare[i])(__uint32_t)(__builtin_constant_p(dlp->d_spare[i]) ? (__uint32_t
)(((__uint32_t)(dlp->d_spare[i]) & 0xff) << 24 |
((__uint32_t)(dlp->d_spare[i]) & 0xff00) << 8 |
((__uint32_t)(dlp->d_spare[i]) & 0xff0000) >> 8
| ((__uint32_t)(dlp->d_spare[i]) & 0xff000000) >>
24) : __swap32md(dlp->d_spare[i]))
;
234
235 dlp->d_magic2 = swap32(dlp->d_magic2)(__uint32_t)(__builtin_constant_p(dlp->d_magic2) ? (__uint32_t
)(((__uint32_t)(dlp->d_magic2) & 0xff) << 24 | (
(__uint32_t)(dlp->d_magic2) & 0xff00) << 8 | ((__uint32_t
)(dlp->d_magic2) & 0xff0000) >> 8 | ((__uint32_t
)(dlp->d_magic2) & 0xff000000) >> 24) : __swap32md
(dlp->d_magic2))
;
236
237 dlp->d_npartitions = swap16(dlp->d_npartitions)(__uint16_t)(__builtin_constant_p(dlp->d_npartitions) ? (__uint16_t
)(((__uint16_t)(dlp->d_npartitions) & 0xffU) << 8
| ((__uint16_t)(dlp->d_npartitions) & 0xff00U) >>
8) : __swap16md(dlp->d_npartitions))
;
238
239 for (i = 0; i < MAXPARTITIONS16; i++) {
240 pp = &dlp->d_partitions[i];
241 pp->p_size = swap32(pp->p_size)(__uint32_t)(__builtin_constant_p(pp->p_size) ? (__uint32_t
)(((__uint32_t)(pp->p_size) & 0xff) << 24 | ((__uint32_t
)(pp->p_size) & 0xff00) << 8 | ((__uint32_t)(pp->
p_size) & 0xff0000) >> 8 | ((__uint32_t)(pp->p_size
) & 0xff000000) >> 24) : __swap32md(pp->p_size))
;
242 pp->p_offset = swap32(pp->p_offset)(__uint32_t)(__builtin_constant_p(pp->p_offset) ? (__uint32_t
)(((__uint32_t)(pp->p_offset) & 0xff) << 24 | ((
__uint32_t)(pp->p_offset) & 0xff00) << 8 | ((__uint32_t
)(pp->p_offset) & 0xff0000) >> 8 | ((__uint32_t)
(pp->p_offset) & 0xff000000) >> 24) : __swap32md
(pp->p_offset))
;
243 if (dlp->d_version == 0) {
244 v0pp = (struct __partitionv0 *)pp;
245 v0pp->p_fsize = swap32(v0pp->p_fsize)(__uint32_t)(__builtin_constant_p(v0pp->p_fsize) ? (__uint32_t
)(((__uint32_t)(v0pp->p_fsize) & 0xff) << 24 | (
(__uint32_t)(v0pp->p_fsize) & 0xff00) << 8 | ((__uint32_t
)(v0pp->p_fsize) & 0xff0000) >> 8 | ((__uint32_t
)(v0pp->p_fsize) & 0xff000000) >> 24) : __swap32md
(v0pp->p_fsize))
;
246 } else {
247 pp->p_offseth = swap16(pp->p_offseth)(__uint16_t)(__builtin_constant_p(pp->p_offseth) ? (__uint16_t
)(((__uint16_t)(pp->p_offseth) & 0xffU) << 8 | (
(__uint16_t)(pp->p_offseth) & 0xff00U) >> 8) : __swap16md
(pp->p_offseth))
;
248 pp->p_sizeh = swap16(pp->p_sizeh)(__uint16_t)(__builtin_constant_p(pp->p_sizeh) ? (__uint16_t
)(((__uint16_t)(pp->p_sizeh) & 0xffU) << 8 | ((__uint16_t
)(pp->p_sizeh) & 0xff00U) >> 8) : __swap16md(pp->
p_sizeh))
;
249 }
250 pp->p_cpg = swap16(pp->p_cpg)(__uint16_t)(__builtin_constant_p(pp->p_cpg) ? (__uint16_t
)(((__uint16_t)(pp->p_cpg) & 0xffU) << 8 | ((__uint16_t
)(pp->p_cpg) & 0xff00U) >> 8) : __swap16md(pp->
p_cpg))
;
251 }
252
253 dlp->d_checksum = 0;
254 dlp->d_checksum = dkcksum(dlp);
255 error = 0;
256 }
257
258 /* XXX should verify lots of other fields and whine a lot */
259
260 /* Initial passed in lp contains the real disk size. */
261 disksize = DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
;
262
263 if (lp != dlp)
264 *lp = *dlp;
265
266 if (lp->d_version == 0) {
267 blkname = findblkname(major(dev)(((unsigned)(dev) >> 8) & 0xff));
268 if (blkname == NULL((void *)0))
269 blkname = findblkname(major(chrtoblk(dev))(((unsigned)(chrtoblk(dev)) >> 8) & 0xff));
270 printf("%s%d has legacy label, please rewrite using "
271 "disklabel(8)\n", blkname, DISKUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) / 16)
);
272
273 lp->d_version = 1;
274 lp->d_secperunith = 0;
275
276 v0pp = (struct __partitionv0 *)lp->d_partitions;
277 pp = lp->d_partitions;
278 for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
279 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->((v0pp-> p_fsize) * (v0pp->p_frag) == 0 ? 0 : (((ffs((v0pp
-> p_fsize) * (v0pp->p_frag)) - 13) << 3) | (ffs(
v0pp->p_frag))))
280 p_fsize, v0pp->p_frag)((v0pp-> p_fsize) * (v0pp->p_frag) == 0 ? 0 : (((ffs((v0pp
-> p_fsize) * (v0pp->p_frag)) - 13) << 3) | (ffs(
v0pp->p_frag))))
;
281 pp->p_offseth = 0;
282 pp->p_sizeh = 0;
283 }
284 }
285
286#ifdef DEBUG
287 if (DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
!= disksize)
288 printf("on-disk disklabel has incorrect disksize (%llu)\n",
289 DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
);
290 if (DL_GETPSIZE(&lp->d_partitions[RAW_PART])(((u_int64_t)(&lp->d_partitions[2])->p_sizeh <<
32) + (&lp->d_partitions[2])->p_size)
!= disksize)
291 printf("on-disk disklabel RAW_PART has incorrect size (%llu)\n",
292 DL_GETPSIZE(&lp->d_partitions[RAW_PART])(((u_int64_t)(&lp->d_partitions[2])->p_sizeh <<
32) + (&lp->d_partitions[2])->p_size)
);
293 if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART])(((u_int64_t)(&lp->d_partitions[2])->p_offseth <<
32) + (&lp->d_partitions[2])->p_offset)
!= 0)
294 printf("on-disk disklabel RAW_PART offset != 0 (%llu)\n",
295 DL_GETPOFFSET(&lp->d_partitions[RAW_PART])(((u_int64_t)(&lp->d_partitions[2])->p_offseth <<
32) + (&lp->d_partitions[2])->p_offset)
);
296#endif
297 DL_SETDSIZE(lp, disksize)do { u_int64_t __x = (disksize); (lp)->d_secperunith = __x
>> 32; (lp)->d_secperunit = __x; } while (0)
;
298 DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize)do { u_int64_t __x = (disksize); (&lp->d_partitions[2]
)->p_sizeh = __x >> 32; (&lp->d_partitions[2]
)->p_size = __x; } while (0)
;
299 DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0)do { u_int64_t __x = (0); (&lp->d_partitions[2])->p_offseth
= __x >> 32; (&lp->d_partitions[2])->p_offset
= __x; } while (0)
;
300 DL_SETBSTART(lp, boundstart)do { u_int64_t __x = (boundstart); (lp)->d_bstarth = __x >>
32; (lp)->d_bstart = __x; } while (0)
;
301 DL_SETBEND(lp, boundend < DL_GETDSIZE(lp) ? boundend : DL_GETDSIZE(lp))do { u_int64_t __x = (boundend < (((u_int64_t)(lp)->d_secperunith
<< 32) + (lp)->d_secperunit) ? boundend : (((u_int64_t
)(lp)->d_secperunith << 32) + (lp)->d_secperunit)
); (lp)->d_bendh = __x >> 32; (lp)->d_bend = __x;
} while (0)
;
302
303 lp->d_checksum = 0;
304 lp->d_checksum = dkcksum(lp);
305 return (0);
306}
307
308/*
309 * Read a disk sector.
310 */
311int
312readdisksector(struct buf *bp, void (*strat)(struct buf *),
313 struct disklabel *lp, u_int64_t sector)
314{
315 bp->b_blkno = DL_SECTOBLK(lp, sector)((sector) * ((lp)->d_secsize / (1 << 9)));
316 bp->b_bcount = lp->d_secsize;
317 bp->b_error = 0;
318 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR)((bp->b_flags) &= ~(0x00008000 | 0x00000000 | 0x00000100
| 0x00000400))
;
319 SET(bp->b_flags, B_BUSY | B_READ | B_RAW)((bp->b_flags) |= (0x00000010 | 0x00008000 | 0x00004000));
320
321 (*strat)(bp);
322
323 return (biowait(bp));
324}
325
326int
327readdoslabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp,
328 daddr_t *partoffp, int spoofonly)
329{
330 uint8_t dosbb[DEV_BSIZE(1 << 9)];
331 struct disklabel nlp;
332 struct disklabel *rlp;
333 daddr_t partoff;
334 int error;
335
336#ifdef DEBUG
337 char devname[32];
338 const char *blkname;
339
340 blkname = findblkname(major(bp->b_dev)(((unsigned)(bp->b_dev) >> 8) & 0xff));
341 if (blkname == NULL((void *)0))
342 blkname = findblkname(major(chrtoblk(bp->b_dev))(((unsigned)(chrtoblk(bp->b_dev)) >> 8) & 0xff));
343 if (blkname == NULL((void *)0))
344 snprintf(devname, sizeof(devname), "<%d, %d>", major(bp->b_dev)(((unsigned)(bp->b_dev) >> 8) & 0xff),
345 minor(bp->b_dev)((unsigned)((bp->b_dev) & 0xff) | (((bp->b_dev) &
0xffff0000) >> 8))
);
346 else
347 snprintf(devname, sizeof(devname), "%s%d", blkname,
348 DISKUNIT(bp->b_dev)(((unsigned)((bp->b_dev) & 0xff) | (((bp->b_dev) &
0xffff0000) >> 8)) / 16)
);
349
350 printf("readdoslabel enter: %s, spoofonly %d, partoffp %sNULL\n",
351 devname, spoofonly, (partoffp == NULL((void *)0)) ? "" : "not ");
352#endif /* DEBUG */
353
354 error = readdisksector(bp, strat, lp, DOSBBSECTOR0);
355 if (error) {
356 DPRINTF("readdoslabel return: %s, %d -- lp unchanged, "
357 "DOSBBSECTOR read error\n", devname, error);
358 return error;
359 }
360 memcpy(dosbb, bp->b_data, sizeof(dosbb))__builtin_memcpy((dosbb), (bp->b_data), (sizeof(dosbb)));
361
362 nlp = *lp;
363 memset(nlp.d_partitions, 0, sizeof(nlp.d_partitions))__builtin_memset((nlp.d_partitions), (0), (sizeof(nlp.d_partitions
)))
;
364 nlp.d_partitions[RAW_PART2] = lp->d_partitions[RAW_PART2];
365 nlp.d_magic = 0;
366
367 error = spoofgpt(bp, strat, dosbb, &nlp, &partoff);
368 if (error)
369 return error;
370 if (nlp.d_magic != DISKMAGIC((u_int32_t)0x82564557))
371 spoofmbr(bp, strat, dosbb, &nlp, &partoff);
372 if (nlp.d_magic != DISKMAGIC((u_int32_t)0x82564557))
373 spooffat(dosbb, &nlp, &partoff);
374 if (nlp.d_magic != DISKMAGIC((u_int32_t)0x82564557)) {
375 DPRINTF("readdoslabel: N/A -- label partition @ "
376 "daddr_t 0 (default)\n");
377 partoff = 0;
378 }
379
380 if (partoffp != NULL((void *)0)) {
381 /*
382 * If a non-zero value is returned writedisklabel() exits with
383 * EIO. If 0 is returned the label sector is read from disk and
384 * lp is copied into it. So leave lp alone!
385 */
386 if (partoff == -1) {
387 DPRINTF("readdoslabel return: %s, ENXIO, lp "
388 "unchanged, *partoffp unchanged\n", devname);
389 return ENXIO6;
390 }
391 *partoffp = partoff;
392 DPRINTF("readdoslabel return: %s, 0, lp unchanged, "
393 "*partoffp set to %lld\n", devname, *partoffp);
394 return 0;
395 }
396
397 nlp.d_magic = lp->d_magic;
398 *lp = nlp;
399 lp->d_checksum = 0;
400 lp->d_checksum = dkcksum(lp);
401
402 if (spoofonly || partoff == -1) {
403 DPRINTF("readdoslabel return: %s, 0, lp spoofed\n",
404 devname);
405 return 0;
406 }
407
408 partoff += DOS_LABELSECTOR1;
409 error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, partoff)((partoff) / ((lp)->d_secsize / (1 << 9))));
410 if (error) {
411 DPRINTF("readdoslabel return: %s, %d, lp read failed\n",
412 devname, error);
413 return bp->b_error;
414 }
415
416 rlp = (struct disklabel *)(bp->b_data + DL_BLKOFFSET(lp, partoff)(((partoff) % ((lp)->d_secsize / (1 << 9))) * (1 <<
9))
);
417 error = checkdisklabel(bp->b_dev, rlp, lp, DL_GETBSTART(rlp)(((u_int64_t)(rlp)->d_bstarth << 32) + (rlp)->d_bstart
)
,
418 DL_GETBEND(rlp)(((u_int64_t)(rlp)->d_bendh << 32) + (rlp)->d_bend
)
);
419
420 DPRINTF("readdoslabel return: %s, %d, checkdisklabel() of daddr_t "
421 "%lld %s\n", devname, error, partoff, error ? "failed" : "ok");
422
423 return error;
424}
425
426/*
427 * Return the index into dp[] of the EFI GPT (0xEE) partition, or -1 if no such
428 * partition exists.
429 *
430 * Copied into sbin/fdisk/mbr.c.
431 */
432int
433gpt_chk_mbr(struct dos_partition *dp, uint64_t dsize)
434{
435 struct dos_partition *dp2;
436 int efi, eficnt, found, i;
437 uint32_t psize;
438
439 found = efi = eficnt = 0;
440 for (dp2 = dp, i = 0; i < NDOSPART4; i++, dp2++) {
441 if (dp2->dp_typ == DOSPTYP_UNUSED0x00)
442 continue;
443 found++;
444 if (dp2->dp_typ != DOSPTYP_EFI0xee)
445 continue;
446 if (letoh32(dp2->dp_start)((__uint32_t)(dp2->dp_start)) != GPTSECTOR1)
447 continue;
448 psize = letoh32(dp2->dp_size)((__uint32_t)(dp2->dp_size));
449 if (psize <= (dsize - GPTSECTOR1) || psize == UINT32_MAX0xffffffffU) {
450 efi = i;
451 eficnt++;
452 }
453 }
454 if (found == 1 && eficnt == 1)
455 return (efi);
456
457 return (-1);
458}
459
460int
461gpt_get_hdr(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp,
462 uint64_t sector, struct gpt_header *gh)
463{
464 struct gpt_header ngh;
465 int error;
466 uint64_t lbaend, lbastart;
467 uint32_t csum;
468 uint32_t size, partsize;
469
470
471 error = readdisksector(bp, strat, lp, sector);
472 if (error)
473 return error;
474
475 memcpy(&ngh, bp->b_data, sizeof(ngh))__builtin_memcpy((&ngh), (bp->b_data), (sizeof(ngh)));
476
477 size = letoh32(ngh.gh_size)((__uint32_t)(ngh.gh_size));
478 partsize = letoh32(ngh.gh_part_size)((__uint32_t)(ngh.gh_part_size));
479 lbaend = letoh64(ngh.gh_lba_end)((__uint64_t)(ngh.gh_lba_end));
480 lbastart = letoh64(ngh.gh_lba_start)((__uint64_t)(ngh.gh_lba_start));
481
482 csum = ngh.gh_csum;
483 ngh.gh_csum = 0;
484 ngh.gh_csum = htole32(crc32(0, (unsigned char *)&ngh, GPTMINHDRSIZE))((__uint32_t)(crc32(0, (unsigned char *)&ngh, 92)));
485
486 if (letoh64(ngh.gh_sig)((__uint64_t)(ngh.gh_sig)) == GPTSIGNATURE0x5452415020494645LL &&
487 letoh32(ngh.gh_rev)((__uint32_t)(ngh.gh_rev)) == GPTREVISION0x10000 &&
488 size == GPTMINHDRSIZE92 && lbastart <= lbaend &&
489 partsize == GPTMINPARTSIZE128 && lp->d_secsize % partsize == 0 &&
490 csum == ngh.gh_csum)
491 *gh = ngh;
492 else
493 memset(gh, 0, sizeof(*gh))__builtin_memset((gh), (0), (sizeof(*gh)));
494
495 return 0;
496}
497
498int
499gpt_get_parts(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp,
500 const struct gpt_header *gh, struct gpt_partition **gp)
501{
502 uint8_t *ngp;
503 int error, i;
504 uint64_t bytes, partlba, sectors;
505 uint32_t partnum, partsize, partcsum;
506
507 partlba = letoh64(gh->gh_part_lba)((__uint64_t)(gh->gh_part_lba));
508 partnum = letoh32(gh->gh_part_num)((__uint32_t)(gh->gh_part_num));
509 partsize = letoh32(gh->gh_part_size)((__uint32_t)(gh->gh_part_size));
510
511 sectors = ((uint64_t)partnum * partsize + lp->d_secsize - 1) /
512 lp->d_secsize;
513
514 ngp = mallocarray(sectors, lp->d_secsize, M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
515 if (ngp == NULL((void *)0)) {
516 *gp = NULL((void *)0);
517 return ENOMEM12;
518 }
519 bytes = sectors * lp->d_secsize;
520
521 for (i = 0; i < sectors; i++) {
522 error = readdisksector(bp, strat, lp, partlba + i);
523 if (error) {
524 free(ngp, M_DEVBUF2, bytes);
525 *gp = NULL((void *)0);
526 return error;
527 }
528 memcpy(ngp + i * lp->d_secsize, bp->b_data, lp->d_secsize)__builtin_memcpy((ngp + i * lp->d_secsize), (bp->b_data
), (lp->d_secsize))
;
529 }
530
531 partcsum = htole32(crc32(0, ngp, partnum * partsize))((__uint32_t)(crc32(0, ngp, partnum * partsize)));
532 if (partcsum != gh->gh_part_csum) {
533 DPRINTF("invalid %s GPT partition array @ %llu\n",
534 (letoh64(gh->gh_lba_self) == GPTSECTOR) ? "Primary" :
535 "Secondary", partlba);
536 free(ngp, M_DEVBUF2, bytes);
537 *gp = NULL((void *)0);
538 } else {
539 *gp = (struct gpt_partition *)ngp;
540 }
541
542 return 0;
543}
544
545int
546gpt_get_fstype(const struct uuid *uuid_part)
547{
548 static int init = 0;
549 static struct uuid uuid_openbsd, uuid_msdos, uuid_chromefs,
550 uuid_linux, uuid_hfs, uuid_unused, uuid_efi_system, uuid_bios_boot;
551 static const uint8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD{ 0x82, 0x4c, 0xc7, 0xa0, 0x36, 0xa8, 0x11, 0xe3, 0x89, 0x0a,
0x95, 0x25, 0x19, 0xad, 0x3f, 0x61 }
;
552 static const uint8_t gpt_uuid_msdos[] = GPT_UUID_MSDOS{ 0xeb, 0xd0, 0xa0, 0xa2, 0xb9, 0xe5, 0x44, 0x33, 0x87, 0xc0,
0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 }
;
553 static const uint8_t gpt_uuid_chromerootfs[] = GPT_UUID_CHROMEROOTFS{ 0x3c, 0xb8, 0xe2, 0x02, 0x3b, 0x7e, 0x47, 0xdd, 0x8a, 0x3c,
0x7f, 0xf2, 0xa1, 0x3c, 0xfc, 0xec }
;
554 static const uint8_t gpt_uuid_linux[] = GPT_UUID_LINUX{ 0x0f, 0xc6, 0x3d, 0xaf, 0x84, 0x83, 0x47, 0x72, 0x8e, 0x79,
0x3d, 0x69, 0xd8, 0x47, 0x7d, 0xe4 }
;
555 static const uint8_t gpt_uuid_hfs[] = GPT_UUID_APPLE_HFS{ 0x48, 0x46, 0x53, 0x00, 0x00, 0x00, 0x11, 0xaa, 0xaa, 0x11,
0x00, 0x30, 0x65, 0x43, 0xec, 0xac }
;
556 static const uint8_t gpt_uuid_unused[] = GPT_UUID_UNUSED{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
;
557 static const uint8_t gpt_uuid_efi_system[] = GPT_UUID_EFI_SYSTEM{ 0xc1, 0x2a, 0x73, 0x28, 0xf8, 0x1f, 0x11, 0xd2, 0xba, 0x4b,
0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }
;
558 static const uint8_t gpt_uuid_bios_boot[] = GPT_UUID_BIOS_BOOT{ 0x21, 0x68, 0x61, 0x48, 0x64, 0x49, 0x6e, 0x6f, 0x74, 0x4e,
0x65, 0x65, 0x64, 0x45, 0x46, 0x49 }
;
559
560 if (init == 0) {
561 uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd);
562 uuid_dec_be(gpt_uuid_msdos, &uuid_msdos);
563 uuid_dec_be(gpt_uuid_chromerootfs, &uuid_chromefs);
564 uuid_dec_be(gpt_uuid_linux, &uuid_linux);
565 uuid_dec_be(gpt_uuid_hfs, &uuid_hfs);
566 uuid_dec_be(gpt_uuid_unused, &uuid_unused);
567 uuid_dec_be(gpt_uuid_efi_system, &uuid_efi_system);
568 uuid_dec_be(gpt_uuid_bios_boot, &uuid_bios_boot);
569 init = 1;
570 }
571
572 if (!memcmp(uuid_part, &uuid_unused, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_unused), (sizeof(struct
uuid)))
)
573 return FS_UNUSED0;
574 else if (!memcmp(uuid_part, &uuid_openbsd, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_openbsd), (sizeof(struct
uuid)))
)
575 return FS_BSDFFS7;
576 else if (!memcmp(uuid_part, &uuid_msdos, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_msdos), (sizeof(struct
uuid)))
)
577 return FS_MSDOS8;
578 else if (!memcmp(uuid_part, &uuid_chromefs, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_chromefs), (sizeof(struct
uuid)))
)
579 return FS_EXT2FS17;
580 else if (!memcmp(uuid_part, &uuid_linux, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_linux), (sizeof(struct
uuid)))
)
581 return FS_EXT2FS17;
582 else if (!memcmp(uuid_part, &uuid_hfs, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_hfs), (sizeof(struct
uuid)))
)
583 return FS_HFS15;
584 else if (!memcmp(uuid_part, &uuid_efi_system, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_efi_system), (sizeof
(struct uuid)))
)
585 return FS_MSDOS8;
586 else if (!memcmp(uuid_part, &uuid_bios_boot, sizeof(struct uuid))__builtin_memcmp((uuid_part), (&uuid_bios_boot), (sizeof(
struct uuid)))
)
587 return FS_BOOT13;
588 else
589 return FS_OTHER10;
590}
591
592int
593spoofgpt(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb,
594 struct disklabel *lp, daddr_t *partoffp)
595{
596 struct dos_partition dp[NDOSPART4];
597 struct gpt_header gh;
598 struct uuid gptype;
599 struct gpt_partition *gp;
600 struct partition *pp;
601 uint64_t lbaend, lbastart, labelsec;
602 uint64_t gpbytes, end, start;
603 daddr_t partoff;
604 unsigned int i, n;
605 int error, fstype, obsdfound;
606 uint32_t partnum;
607 uint16_t sig;
608
609 gp = NULL((void *)0);
610 gpbytes = 0;
611
612 memcpy(dp, dosbb + DOSPARTOFF, sizeof(dp))__builtin_memcpy((dp), (dosbb + 446), (sizeof(dp)));
613 memcpy(&sig, dosbb + DOSMBR_SIGNATURE_OFF, sizeof(sig))__builtin_memcpy((&sig), (dosbb + (0x1fe)), (sizeof(sig))
)
;
614
615 if (letoh16(sig)((__uint16_t)(sig)) != DOSMBR_SIGNATURE(0xaa55) ||
616 gpt_chk_mbr(dp, DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
) == -1)
617 return 0;
618
619 error = gpt_get_hdr(bp, strat, lp, GPTSECTOR1, &gh);
620 if (error == 0 && letoh64(gh.gh_sig)((__uint64_t)(gh.gh_sig)) == GPTSIGNATURE0x5452415020494645LL)
621 error = gpt_get_parts(bp, strat, lp, &gh, &gp);
622
623 if (error || letoh64(gh.gh_sig)((__uint64_t)(gh.gh_sig)) != GPTSIGNATURE0x5452415020494645LL || gp == NULL((void *)0)) {
624 error = gpt_get_hdr(bp, strat, lp, DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- 1, &gh);
625 if (error == 0 && letoh64(gh.gh_sig)((__uint64_t)(gh.gh_sig)) == GPTSIGNATURE0x5452415020494645LL)
626 error = gpt_get_parts(bp, strat, lp, &gh, &gp);
627 }
628
629 if (error)
630 return error;
631 if (gp == NULL((void *)0))
632 return ENXIO6;
633
634 lbastart = letoh64(gh.gh_lba_start)((__uint64_t)(gh.gh_lba_start));
635 lbaend = letoh64(gh.gh_lba_end)((__uint64_t)(gh.gh_lba_end));
636 partnum = letoh32(gh.gh_part_num)((__uint32_t)(gh.gh_part_num));
637
638 n = 'i' - 'a'; /* Start spoofing at 'i', a.k.a. 8. */
639
640 DL_SETBSTART(lp, lbastart)do { u_int64_t __x = (lbastart); (lp)->d_bstarth = __x >>
32; (lp)->d_bstart = __x; } while (0)
;
641 DL_SETBEND(lp, lbaend + 1)do { u_int64_t __x = (lbaend + 1); (lp)->d_bendh = __x >>
32; (lp)->d_bend = __x; } while (0)
;
642 partoff = DL_SECTOBLK(lp, lbastart)((lbastart) * ((lp)->d_secsize / (1 << 9)));
643 obsdfound = 0;
644 for (i = 0; i < partnum; i++) {
645 if (letoh64(gp[i].gp_attrs)((__uint64_t)(gp[i].gp_attrs)) & GPTPARTATTR_REQUIRED(1ULL << 0)) {
646 DPRINTF("spoofgpt: Skipping partition %u (REQUIRED)\n",
647 i);
648 continue;
649 }
650
651 start = letoh64(gp[i].gp_lba_start)((__uint64_t)(gp[i].gp_lba_start));
652 if (start > lbaend || start < lbastart)
653 continue;
654
655 end = letoh64(gp[i].gp_lba_end)((__uint64_t)(gp[i].gp_lba_end));
656 if (start > end)
657 continue;
658
659 uuid_dec_le(&gp[i].gp_type, &gptype);
660 fstype = gpt_get_fstype(&gptype);
661 if (obsdfound && fstype == FS_BSDFFS7)
662 continue;
663
664 if (fstype == FS_BSDFFS7) {
665 obsdfound = 1;
666 partoff = DL_SECTOBLK(lp, start)((start) * ((lp)->d_secsize / (1 << 9)));
667 labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR)((partoff + 1) / ((lp)->d_secsize / (1 << 9)));
668 if (labelsec > ((end < lbaend) ? end : lbaend))
669 partoff = -1;
670 DL_SETBSTART(lp, start)do { u_int64_t __x = (start); (lp)->d_bstarth = __x >>
32; (lp)->d_bstart = __x; } while (0)
;
671 DL_SETBEND(lp, end + 1)do { u_int64_t __x = (end + 1); (lp)->d_bendh = __x >>
32; (lp)->d_bend = __x; } while (0)
;
672 continue;
673 }
674
675 if (partoff != -1) {
676 labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR)((partoff + 1) / ((lp)->d_secsize / (1 << 9)));
677 if (labelsec >= start && labelsec <= end)
678 partoff = -1;
679 }
680
681 if (n < MAXPARTITIONS16 && end <= lbaend) {
682 pp = &lp->d_partitions[n];
683 n++;
684 pp->p_fstype = fstype;
685 DL_SETPOFFSET(pp, start)do { u_int64_t __x = (start); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
686 DL_SETPSIZE(pp, end - start + 1)do { u_int64_t __x = (end - start + 1); (pp)->p_sizeh = __x
>> 32; (pp)->p_size = __x; } while (0)
;
687 }
688 }
689
690 lp->d_magic = DISKMAGIC((u_int32_t)0x82564557);
691 *partoffp = partoff;
692 free(gp, M_DEVBUF2, gpbytes);
693
694#ifdef DEBUG
695 printf("readdoslabel: GPT -- ");
696 if (partoff == -1)
697 printf("no label partition\n");
698 else if (obsdfound == 0)
699 printf("label partition @ daddr_t %lld (free space)\n", partoff);
700 else
701 printf("label partition @ daddr_t %lld (A6)\n", partoff);
702#endif /* DEBUG */
703
704 return 0;
705}
706
707int
708mbr_get_fstype(const uint8_t dp_typ)
709{
710 switch (dp_typ) {
711 case DOSPTYP_OPENBSD0xa6:
712 return FS_BSDFFS7;
713 case DOSPTYP_UNUSED0x00:
714 return FS_UNUSED0;
715 case DOSPTYP_LINUX0x83:
716 return FS_EXT2FS17;
717 case DOSPTYP_NTFS0x07:
718 return FS_NTFS20;
719 case DOSPTYP_EFISYS0xef:
720 case DOSPTYP_FAT120x01:
721 case DOSPTYP_FAT16S0x04:
722 case DOSPTYP_FAT16B0x06:
723 case DOSPTYP_FAT16L0x0e:
724 case DOSPTYP_FAT320x0b:
725 case DOSPTYP_FAT32L0x0c:
726 return FS_MSDOS8;
727 case DOSPTYP_EFI0xee:
728 case DOSPTYP_EXTEND0x05:
729 case DOSPTYP_EXTENDL0x0f:
730 default:
731 return FS_OTHER10;
732 }
733}
734
735void
736spoofmbr(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb,
737 struct disklabel *lp, daddr_t *partoffp)
738{
739 struct dos_partition dp[NDOSPART4];
740 struct partition *pp;
741 uint64_t sector = DOSBBSECTOR0;
742 uint64_t start, end;
743 daddr_t labeloff, partoff;
744 unsigned int i, n, parts;
745 int wander = 1, ebr = 0;
746 int error, obsdfound;
747 uint32_t extoff = 0;
748 uint16_t sig;
749 uint8_t fstype;
750
751 memcpy(&sig, dosbb + DOSMBR_SIGNATURE_OFF, sizeof(sig))__builtin_memcpy((&sig), (dosbb + (0x1fe)), (sizeof(sig))
)
;
752 if (letoh16(sig)((__uint16_t)(sig)) != DOSMBR_SIGNATURE(0xaa55))
753 return;
754 memcpy(dp, dosbb + DOSPARTOFF, sizeof(dp))__builtin_memcpy((dp), (dosbb + 446), (sizeof(dp)));
755
756 obsdfound = 0;
757 partoff = 0;
758 parts = 0;
759 n = 'i' - 'a';
760 while (wander && ebr < DOS_MAXEBR256) {
761 ebr++;
762 wander = 0;
763 if (sector < extoff)
764 sector = extoff;
765
766 error = 0;
767 if (sector != DOSBBSECTOR0) {
768 error = readdisksector(bp, strat, lp, sector);
769 if (error)
770 break;
771 memcpy(&sig, bp->b_data + DOSMBR_SIGNATURE_OFF,__builtin_memcpy((&sig), (bp->b_data + (0x1fe)), (sizeof
(sig)))
772 sizeof(sig))__builtin_memcpy((&sig), (bp->b_data + (0x1fe)), (sizeof
(sig)))
;
773 if (letoh16(sig)((__uint16_t)(sig)) != DOSMBR_SIGNATURE(0xaa55))
774 break;
775 memcpy(dp, bp->b_data + DOSPARTOFF, sizeof(dp))__builtin_memcpy((dp), (bp->b_data + 446), (sizeof(dp)));
776 }
777
778 for (i = 0; i < NDOSPART4; i++) {
779 if (letoh32(dp[i].dp_size)((__uint32_t)(dp[i].dp_size)) == 0)
780 continue;
781 if (obsdfound && dp[i].dp_typ == DOSPTYP_OPENBSD0xa6)
782 continue;
783
784 if (dp[i].dp_typ != DOSPTYP_OPENBSD0xa6) {
785 if (letoh32(dp[i].dp_start)((__uint32_t)(dp[i].dp_start)) > DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
)
786 continue;
787 if (letoh32(dp[i].dp_size)((__uint32_t)(dp[i].dp_size)) > DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
)
788 continue;
789 }
790
791 start = sector + letoh32(dp[i].dp_start)((__uint32_t)(dp[i].dp_start));
792 end = start + letoh32(dp[i].dp_size)((__uint32_t)(dp[i].dp_size));
793
794 parts++;
795 if (obsdfound == 0) {
796 labeloff = partoff + DOS_LABELSECTOR1;
797 if (labeloff >= DL_SECTOBLK(lp, start)((start) * ((lp)->d_secsize / (1 << 9))) &&
798 labeloff < DL_SECTOBLK(lp, end)((end) * ((lp)->d_secsize / (1 << 9))))
799 partoff = -1;
800 }
801
802 switch (dp[i].dp_typ) {
803 case DOSPTYP_OPENBSD0xa6:
804 obsdfound = 1;
805 partoff = DL_SECTOBLK(lp, start)((start) * ((lp)->d_secsize / (1 << 9)));
806 labeloff = partoff + DOS_LABELSECTOR1;
807 if (labeloff >= DL_SECTOBLK(lp, end)((end) * ((lp)->d_secsize / (1 << 9))))
808 partoff = -1;
809 DL_SETBSTART(lp, start)do { u_int64_t __x = (start); (lp)->d_bstarth = __x >>
32; (lp)->d_bstart = __x; } while (0)
;
810 DL_SETBEND(lp, end)do { u_int64_t __x = (end); (lp)->d_bendh = __x >> 32
; (lp)->d_bend = __x; } while (0)
;
811 continue;
812 case DOSPTYP_EFI0xee:
813 continue;
814 case DOSPTYP_EXTEND0x05:
815 case DOSPTYP_EXTENDL0x0f:
816 sector = start + extoff;
817 if (extoff == 0) {
818 extoff = start;
819 sector = 0;
820 }
821 wander = 1;
822 continue;
823 default:
824 break;
825 }
826
827 fstype = mbr_get_fstype(dp[i].dp_typ);
828 if (n < MAXPARTITIONS16) {
829 pp = &lp->d_partitions[n++];
830 pp->p_fstype = fstype;
831 if (start)
832 DL_SETPOFFSET(pp, start)do { u_int64_t __x = (start); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
833 DL_SETPSIZE(pp, end - start)do { u_int64_t __x = (end - start); (pp)->p_sizeh = __x >>
32; (pp)->p_size = __x; } while (0)
;
834 }
835 }
836 }
837
838 if (parts > 0) {
839 lp->d_magic = DISKMAGIC((u_int32_t)0x82564557);
840 *partoffp = partoff;
841#ifdef DEBUG
842 printf("readdoslabel: MBR -- ");
843 if (partoff == -1)
844 printf("no label partition\n");
845 else if (obsdfound == 0)
846 printf("label partition @ daddr_t %lld (free space)\n", partoff);
847 else
848 printf("label partition @ daddr_t %lld (A6)\n", partoff);
849#endif /* DEBUG */
850 }
851}
852
853void
854spooffat(const uint8_t *dosbb, struct disklabel *lp, daddr_t *partoffp)
855{
856 uint16_t secsize;
857
858#define VALID_JMP(_p)(((_p)[0] == 0xeb && (_p)[2] == 0x90) || (_p)[0] == 0xe9
)
(((_p)[0] == 0xeb && (_p)[2] == 0x90) || (_p)[0] == 0xe9)
859#define VALID_FAT(_p)((_p)[16] == 1 || (_p)[16] == 2) ((_p)[16] == 1 || (_p)[16] == 2)
860#define VALID_SEC(_s)((_s) >= (1 << 9) && (_s) <= 4096 &&
((_s) % 512 == 0))
((_s) >= DEV_BSIZE(1 << 9) && (_s) <= 4096 && ((_s) % 512 == 0))
861
862 memcpy(&secsize, dosbb + 11, sizeof(secsize))__builtin_memcpy((&secsize), (dosbb + 11), (sizeof(secsize
)))
;
863 secsize = letoh16(secsize)((__uint16_t)(secsize));
864
865 if (VALID_JMP(dosbb)(((dosbb)[0] == 0xeb && (dosbb)[2] == 0x90) || (dosbb
)[0] == 0xe9)
&& VALID_SEC(secsize)((secsize) >= (1 << 9) && (secsize) <= 4096
&& ((secsize) % 512 == 0))
&& VALID_FAT(dosbb)((dosbb)[16] == 1 || (dosbb)[16] == 2)) {
866 lp->d_partitions['i' - 'a'] = lp->d_partitions[RAW_PART2];
867 lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS8;
868 *partoffp = -1;
869 lp->d_magic = DISKMAGIC((u_int32_t)0x82564557);
870 DPRINTF("readdoslabel: FAT -- no label partition\n");
871 }
872}
873
874/*
875 * Check new disk label for sensibility before setting it.
876 */
877int
878setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
879{
880 struct partition *opp, *npp;
881 struct disk *dk;
882 int i;
883
884 /* sanity clause */
885 if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
886 (nlp->d_secsize % DEV_BSIZE(1 << 9)) != 0)
887 return (EINVAL22);
888
889 /* special case to allow disklabel to be invalidated */
890 if (nlp->d_magic == 0xffffffff) {
891 *olp = *nlp;
892 return (0);
893 }
894
895 if (nlp->d_magic != DISKMAGIC((u_int32_t)0x82564557) || nlp->d_magic2 != DISKMAGIC((u_int32_t)0x82564557) ||
896 dkcksum(nlp) != 0)
897 return (EINVAL22);
898
899 /* XXX missing check if other dos partitions will be overwritten */
900
901 for (i = 0; i < MAXPARTITIONS16; i++) {
902 opp = &olp->d_partitions[i];
903 npp = &nlp->d_partitions[i];
904 if ((openmask & (1 << i)) &&
905 (DL_GETPOFFSET(npp)(((u_int64_t)(npp)->p_offseth << 32) + (npp)->p_offset
)
!= DL_GETPOFFSET(opp)(((u_int64_t)(opp)->p_offseth << 32) + (opp)->p_offset
)
||
906 DL_GETPSIZE(npp)(((u_int64_t)(npp)->p_sizeh << 32) + (npp)->p_size
)
< DL_GETPSIZE(opp)(((u_int64_t)(opp)->p_sizeh << 32) + (opp)->p_size
)
))
907 return (EBUSY16);
908 /*
909 * Copy internally-set partition information
910 * if new label doesn't include it. XXX
911 */
912 if (npp->p_fstype == FS_UNUSED0 && opp->p_fstype != FS_UNUSED0) {
913 npp->p_fragblock = opp->p_fragblock;
914 npp->p_cpg = opp->p_cpg;
915 }
916 }
917
918 /* Generate a UID if the disklabel does not already have one. */
919 if (duid_iszero(nlp->d_uid)) {
920 do {
921 arc4random_buf(nlp->d_uid, sizeof(nlp->d_uid));
922 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
923 if (dk->dk_label &&
924 duid_equal(dk->dk_label->d_uid, nlp->d_uid))
925 break;
926 } while (dk != NULL((void *)0) || duid_iszero(nlp->d_uid));
927 }
928
929 /* Preserve the disk size and RAW_PART values. */
930 DL_SETDSIZE(nlp, DL_GETDSIZE(olp))do { u_int64_t __x = ((((u_int64_t)(olp)->d_secperunith <<
32) + (olp)->d_secperunit)); (nlp)->d_secperunith = __x
>> 32; (nlp)->d_secperunit = __x; } while (0)
;
931 npp = &nlp->d_partitions[RAW_PART2];
932 DL_SETPOFFSET(npp, 0)do { u_int64_t __x = (0); (npp)->p_offseth = __x >> 32
; (npp)->p_offset = __x; } while (0)
;
933 DL_SETPSIZE(npp, DL_GETDSIZE(nlp))do { u_int64_t __x = ((((u_int64_t)(nlp)->d_secperunith <<
32) + (nlp)->d_secperunit)); (npp)->p_sizeh = __x >>
32; (npp)->p_size = __x; } while (0)
;
934
935 nlp->d_checksum = 0;
936 nlp->d_checksum = dkcksum(nlp);
937 *olp = *nlp;
938
939 disk_change = 1;
940
941 return (0);
942}
943
944/*
945 * Determine the size of the transfer, and make sure it is within the
946 * boundaries of the partition. Adjust transfer if needed, and signal errors or
947 * early completion.
948 */
949int
950bounds_check_with_label(struct buf *bp, struct disklabel *lp)
951{
952 struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)(((unsigned)((bp->b_dev) & 0xff) | (((bp->b_dev) &
0xffff0000) >> 8)) % 16)
];
953 daddr_t partblocks, sz;
954
955 /* Avoid division by zero, negative offsets, and negative sizes. */
956 if (lp->d_secpercyl == 0 || bp->b_blkno < 0 || bp->b_bcount < 0)
957 goto bad;
958
959 /* Ensure transfer is a whole number of aligned sectors. */
960 if ((bp->b_blkno % DL_BLKSPERSEC(lp)((lp)->d_secsize / (1 << 9))) != 0 ||
961 (bp->b_bcount % lp->d_secsize) != 0)
962 goto bad;
963
964 /* Ensure transfer starts within partition boundary. */
965 partblocks = DL_SECTOBLK(lp, DL_GETPSIZE(p))(((((u_int64_t)(p)->p_sizeh << 32) + (p)->p_size)
) * ((lp)->d_secsize / (1 << 9)))
;
966 if (bp->b_blkno > partblocks)
967 goto bad;
968
969 /* If exactly at end of partition or null transfer, return EOF. */
970 if (bp->b_blkno == partblocks || bp->b_bcount == 0)
971 goto done;
972
973 /* Truncate request if it extends past the end of the partition. */
974 sz = bp->b_bcount >> DEV_BSHIFT9;
975 if (sz > partblocks - bp->b_blkno) {
976 sz = partblocks - bp->b_blkno;
977 bp->b_bcount = sz << DEV_BSHIFT9;
978 }
979
980 return (0);
981
982 bad:
983 bp->b_error = EINVAL22;
984 bp->b_flags |= B_ERROR0x00000400;
985 done:
986 bp->b_resid = bp->b_bcount;
987 return (-1);
988}
989
990/*
991 * Disk error is the preface to plaintive error messages
992 * about failing disk transfers. It prints messages of the form
993
994hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
995
996 * if the offset of the error in the transfer and a disk label
997 * are both available. blkdone should be -1 if the position of the error
998 * is unknown; the disklabel pointer may be null from drivers that have not
999 * been converted to use them. The message is printed with printf
1000 * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
1001 * The message should be completed (with at least a newline) with printf
1002 * or addlog, respectively. There is no trailing space.
1003 */
1004void
1005diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
1006 struct disklabel *lp)
1007{
1008 int unit = DISKUNIT(bp->b_dev)(((unsigned)((bp->b_dev) & 0xff) | (((bp->b_dev) &
0xffff0000) >> 8)) / 16)
, part = DISKPART(bp->b_dev)(((unsigned)((bp->b_dev) & 0xff) | (((bp->b_dev) &
0xffff0000) >> 8)) % 16)
;
1009 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)));
1010 char partname = 'a' + part;
1011 daddr_t sn;
1012
1013 if (pri != LOG_PRINTF-1) {
1014 log(pri, "%s", "");
1015 pr = addlog;
1016 } else
1017 pr = printf;
1018 (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
1019 bp->b_flags & B_READ0x00008000 ? "read" : "writ");
1020 sn = bp->b_blkno;
1021 if (bp->b_bcount <= DEV_BSIZE(1 << 9))
1022 (*pr)("%lld", (long long)sn);
1023 else {
1024 if (blkdone >= 0) {
1025 sn += blkdone;
1026 (*pr)("%lld of ", (long long)sn);
1027 }
1028 (*pr)("%lld-%lld", (long long)bp->b_blkno,
1029 (long long)(bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE(1 << 9)));
1030 }
1031 if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
1032 sn += DL_SECTOBLK(lp, DL_GETPOFFSET(&lp->d_partitions[part]))(((((u_int64_t)(&lp->d_partitions[part])->p_offseth
<< 32) + (&lp->d_partitions[part])->p_offset
)) * ((lp)->d_secsize / (1 << 9)))
;
1033 (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, (long long)sn,
1034 (long long)(sn / DL_SECTOBLK(lp, lp->d_secpercyl)((lp->d_secpercyl) * ((lp)->d_secsize / (1 << 9))
)
));
1035 sn %= DL_SECTOBLK(lp, lp->d_secpercyl)((lp->d_secpercyl) * ((lp)->d_secsize / (1 << 9))
)
;
1036 (*pr)(" tn %lld sn %lld)",
1037 (long long)(sn / DL_SECTOBLK(lp, lp->d_nsectors)((lp->d_nsectors) * ((lp)->d_secsize / (1 << 9)))),
1038 (long long)(sn % DL_SECTOBLK(lp, lp->d_nsectors)((lp->d_nsectors) * ((lp)->d_secsize / (1 << 9)))));
1039 }
1040}
1041
1042/*
1043 * Initialize the disklist. Called by main() before autoconfiguration.
1044 */
1045void
1046disk_init(void)
1047{
1048
1049 TAILQ_INIT(&disklist)do { (&disklist)->tqh_first = ((void *)0); (&disklist
)->tqh_last = &(&disklist)->tqh_first; } while (
0)
;
1050 disk_count = disk_change = 0;
1051}
1052
1053int
1054disk_construct(struct disk *diskp)
1055{
1056 rw_init_flags(&diskp->dk_lock, "dklk", RWL_IS_VNODE)_rw_init_flags(&diskp->dk_lock, "dklk", 0x04, ((void *
)0))
;
1057 mtx_init(&diskp->dk_mtx, IPL_BIO)do { (void)(((void *)0)); (void)(0); __mtx_init((&diskp->
dk_mtx), ((((0x3)) > 0x0 && ((0x3)) < 0x9) ? 0x9
: ((0x3)))); } while (0)
;
1058
1059 diskp->dk_flags |= DKF_CONSTRUCTED0x0001;
1060
1061 return (0);
1062}
1063
1064/*
1065 * Attach a disk.
1066 */
1067void
1068disk_attach(struct device *dv, struct disk *diskp)
1069{
1070 int majdev;
1071
1072 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/subr_disk.c"
, 1072, "_kernel_lock_held()"))
;
1073
1074 if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED)((diskp->dk_flags) & (0x0001)))
1075 disk_construct(diskp);
1076
1077 /*
1078 * Allocate and initialize the disklabel structures. Note that
1079 * it's not safe to sleep here, since we're probably going to be
1080 * called during autoconfiguration.
1081 */
1082 diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF2,
1083 M_NOWAIT0x0002|M_ZERO0x0008);
1084 if (diskp->dk_label == NULL((void *)0))
1085 panic("disk_attach: can't allocate storage for disklabel");
1086
1087 /*
1088 * Set the attached timestamp.
1089 */
1090 microuptime(&diskp->dk_attachtime);
1091
1092 /*
1093 * Link into the disklist.
1094 */
1095 TAILQ_INSERT_TAIL(&disklist, diskp, dk_link)do { (diskp)->dk_link.tqe_next = ((void *)0); (diskp)->
dk_link.tqe_prev = (&disklist)->tqh_last; *(&disklist
)->tqh_last = (diskp); (&disklist)->tqh_last = &
(diskp)->dk_link.tqe_next; } while (0)
;
1096 ++disk_count;
1097 disk_change = 1;
1098
1099 /*
1100 * Store device structure and number for later use.
1101 */
1102 diskp->dk_device = dv;
1103 diskp->dk_devno = NODEV(dev_t)(-1);
1104 if (dv != NULL((void *)0)) {
1105 majdev = findblkmajor(dv);
1106 if (majdev >= 0)
1107 diskp->dk_devno =
1108 MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART)(((dev_t)(((((majdev)) & 0xff) << 8) | ((((((dv->
dv_unit)) * 16) + ((2)))) & 0xff) | (((((((dv->dv_unit
)) * 16) + ((2)))) & 0xffff00) << 8))))
;
1109
1110 if (diskp->dk_devno != NODEV(dev_t)(-1)) {
1111 struct disk_attach_task *dat;
1112
1113 dat = malloc(sizeof(*dat), M_TEMP127, M_WAITOK0x0001);
1114
1115 /* XXX: Assumes dk is part of the device softc. */
1116 device_ref(dv);
1117 dat->dk = diskp;
1118
1119 task_set(&dat->task, disk_attach_callback, dat);
1120 task_add(systq, &dat->task);
1121 }
1122 }
1123
1124 if (softraid_disk_attach)
1125 softraid_disk_attach(diskp, 1);
1126}
1127
1128void
1129disk_attach_callback(void *xdat)
1130{
1131 struct disk_attach_task *dat = xdat;
1132 struct disk *dk = dat->dk;
1133 struct disklabel dl;
1134 char errbuf[100];
1135
1136 free(dat, M_TEMP127, sizeof(*dat));
1137
1138 if (dk->dk_flags & (DKF_OPENED0x0002 | DKF_NOLABELREAD0x0004))
1139 goto done;
1140
1141 /* Read disklabel. */
1142 if (disk_readlabel(&dl, dk->dk_devno, errbuf, sizeof(errbuf)) == NULL((void *)0)) {
1143 enqueue_randomness(dl.d_checksum);
1144 }
1145
1146done:
1147 dk->dk_flags |= DKF_OPENED0x0002;
1148 device_unref(dk->dk_device);
1149 wakeup(dk);
1150}
1151
1152/*
1153 * Detach a disk.
1154 */
1155void
1156disk_detach(struct disk *diskp)
1157{
1158 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/subr_disk.c"
, 1158, "_kernel_lock_held()"))
;
1159
1160 if (softraid_disk_attach)
1161 softraid_disk_attach(diskp, -1);
1162
1163 /*
1164 * Free the space used by the disklabel structures.
1165 */
1166 free(diskp->dk_label, M_DEVBUF2, sizeof(*diskp->dk_label));
1167
1168 /*
1169 * Remove from the disklist.
1170 */
1171 TAILQ_REMOVE(&disklist, diskp, dk_link)do { if (((diskp)->dk_link.tqe_next) != ((void *)0)) (diskp
)->dk_link.tqe_next->dk_link.tqe_prev = (diskp)->dk_link
.tqe_prev; else (&disklist)->tqh_last = (diskp)->dk_link
.tqe_prev; *(diskp)->dk_link.tqe_prev = (diskp)->dk_link
.tqe_next; ((diskp)->dk_link.tqe_prev) = ((void *)-1); ((diskp
)->dk_link.tqe_next) = ((void *)-1); } while (0)
;
1172 disk_change = 1;
1173 if (--disk_count < 0)
1174 panic("disk_detach: disk_count < 0");
1175}
1176
1177int
1178disk_openpart(struct disk *dk, int part, int fmt, int haslabel)
1179{
1180 KASSERT(part >= 0 && part < MAXPARTITIONS)((part >= 0 && part < 16) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/kern/subr_disk.c", 1180, "part >= 0 && part < MAXPARTITIONS"
))
;
1181
1182 /* Unless opening the raw partition, check that the partition exists. */
1183 if (part != RAW_PART2 && (!haslabel ||
1184 part >= dk->dk_label->d_npartitions ||
1185 dk->dk_label->d_partitions[part].p_fstype == FS_UNUSED0))
1186 return (ENXIO6);
1187
1188 /* Ensure the partition doesn't get changed under our feet. */
1189 switch (fmt) {
1190 case S_IFCHR0020000:
1191 dk->dk_copenmask |= (1 << part);
1192 break;
1193 case S_IFBLK0060000:
1194 dk->dk_bopenmask |= (1 << part);
1195 break;
1196 }
1197 dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
1198
1199 return (0);
1200}
1201
1202void
1203disk_closepart(struct disk *dk, int part, int fmt)
1204{
1205 KASSERT(part >= 0 && part < MAXPARTITIONS)((part >= 0 && part < 16) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/kern/subr_disk.c", 1205, "part >= 0 && part < MAXPARTITIONS"
))
;
1206
1207 switch (fmt) {
1208 case S_IFCHR0020000:
1209 dk->dk_copenmask &= ~(1 << part);
1210 break;
1211 case S_IFBLK0060000:
1212 dk->dk_bopenmask &= ~(1 << part);
1213 break;
1214 }
1215 dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
1216}
1217
1218void
1219disk_gone(int (*open)(dev_t, int, int, struct proc *), int unit)
1220{
1221 int bmaj, cmaj, mn;
1222
1223 /* Locate the lowest minor number to be detached. */
1224 mn = DISKMINOR(unit, 0)(((unit) * 16) + (0));
1225
1226 for (bmaj = 0; bmaj < nblkdev; bmaj++)
1227 if (bdevsw[bmaj].d_open == open)
1228 vdevgone(bmaj, mn, mn + MAXPARTITIONS16 - 1, VBLK);
1229 for (cmaj = 0; cmaj < nchrdev; cmaj++)
1230 if (cdevsw[cmaj].d_open == open)
1231 vdevgone(cmaj, mn, mn + MAXPARTITIONS16 - 1, VCHR);
1232}
1233
1234/*
1235 * Increment a disk's busy counter. If the counter is going from
1236 * 0 to 1, set the timestamp.
1237 */
1238void
1239disk_busy(struct disk *diskp)
1240{
1241
1242 /*
1243 * XXX We'd like to use something as accurate as microtime(),
1244 * but that doesn't depend on the system TOD clock.
1245 */
1246 mtx_enter(&diskp->dk_mtx);
1247 if (diskp->dk_busy++ == 0)
1248 microuptime(&diskp->dk_timestamp);
1249 mtx_leave(&diskp->dk_mtx);
1250}
1251
1252/*
1253 * Decrement a disk's busy counter, increment the byte count, total busy
1254 * time, and reset the timestamp.
1255 */
1256void
1257disk_unbusy(struct disk *diskp, long bcount, daddr_t blkno, int read)
1258{
1259 struct timeval dv_time, diff_time;
1260
1261 mtx_enter(&diskp->dk_mtx);
1262
1263 if (diskp->dk_busy-- == 0)
1264 printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
1265
1266 microuptime(&dv_time);
1267
1268 timersub(&dv_time, &diskp->dk_timestamp, &diff_time)do { (&diff_time)->tv_sec = (&dv_time)->tv_sec -
(&diskp->dk_timestamp)->tv_sec; (&diff_time)->
tv_usec = (&dv_time)->tv_usec - (&diskp->dk_timestamp
)->tv_usec; if ((&diff_time)->tv_usec < 0) { (&
diff_time)->tv_sec--; (&diff_time)->tv_usec += 1000000
; } } while (0)
;
1269 timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time)do { (&diskp->dk_time)->tv_sec = (&diskp->dk_time
)->tv_sec + (&diff_time)->tv_sec; (&diskp->dk_time
)->tv_usec = (&diskp->dk_time)->tv_usec + (&
diff_time)->tv_usec; if ((&diskp->dk_time)->tv_usec
>= 1000000) { (&diskp->dk_time)->tv_sec++; (&
diskp->dk_time)->tv_usec -= 1000000; } } while (0)
;
1270
1271 diskp->dk_timestamp = dv_time;
1272 if (bcount > 0) {
1273 if (read) {
1274 diskp->dk_rbytes += bcount;
1275 diskp->dk_rxfer++;
1276 } else {
1277 diskp->dk_wbytes += bcount;
1278 diskp->dk_wxfer++;
1279 }
1280 } else
1281 diskp->dk_seek++;
1282
1283 mtx_leave(&diskp->dk_mtx);
1284
1285 enqueue_randomness(bcount ^ diff_time.tv_usec ^
1286 (blkno >> 32) ^ (blkno & 0xffffffff));
1287}
1288
1289int
1290disk_lock(struct disk *dk)
1291{
1292 return (rw_enter(&dk->dk_lock, RW_WRITE0x0001UL|RW_INTR0x0010UL));
1293}
1294
1295void
1296disk_lock_nointr(struct disk *dk)
1297{
1298 rw_enter_write(&dk->dk_lock);
1299}
1300
1301void
1302disk_unlock(struct disk *dk)
1303{
1304 rw_exit_write(&dk->dk_lock);
1305}
1306
1307int
1308dk_mountroot(void)
1309{
1310 char errbuf[100];
1311 int part = DISKPART(rootdev)(((unsigned)((rootdev) & 0xff) | (((rootdev) & 0xffff0000
) >> 8)) % 16)
;
1312 int (*mountrootfn)(void);
1313 struct disklabel dl;
1314 char *error;
1315
1316 error = disk_readlabel(&dl, rootdev, errbuf, sizeof(errbuf));
1317 if (error)
1318 panic("%s", error);
1319
1320 if (DL_GETPSIZE(&dl.d_partitions[part])(((u_int64_t)(&dl.d_partitions[part])->p_sizeh <<
32) + (&dl.d_partitions[part])->p_size)
== 0)
1321 panic("root filesystem has size 0");
1322 switch (dl.d_partitions[part].p_fstype) {
1323#ifdef EXT2FS1
1324 case FS_EXT2FS17:
1325 {
1326 extern int ext2fs_mountroot(void);
1327 mountrootfn = ext2fs_mountroot;
1328 }
1329 break;
1330#endif
1331#ifdef FFS1
1332 case FS_BSDFFS7:
1333 {
1334 extern int ffs_mountroot(void);
1335 mountrootfn = ffs_mountroot;
1336 }
1337 break;
1338#endif
1339#ifdef CD96601
1340 case FS_ISO966012:
1341 {
1342 extern int cd9660_mountroot(void);
1343 mountrootfn = cd9660_mountroot;
1344 }
1345 break;
1346#endif
1347 default:
1348#ifdef FFS1
1349 {
1350 extern int ffs_mountroot(void);
1351
1352 printf("filesystem type %d not known.. assuming ffs\n",
1353 dl.d_partitions[part].p_fstype);
1354 mountrootfn = ffs_mountroot;
1355 }
1356#else
1357 panic("disk 0x%x filesystem type %d not known",
1358 rootdev, dl.d_partitions[part].p_fstype);
1359#endif
1360 }
1361 return (*mountrootfn)();
1362}
1363
1364struct device *
1365getdisk(char *str, int len, int defpart, dev_t *devp)
1366{
1367 struct device *dv;
1368
1369 if ((dv = parsedisk(str, len, defpart, devp)) == NULL((void *)0)) {
1370 printf("use one of: exit");
1371 TAILQ_FOREACH(dv, &alldevs, dv_list)for((dv) = ((&alldevs)->tqh_first); (dv) != ((void *)0
); (dv) = ((dv)->dv_list.tqe_next))
{
1372 if (dv->dv_class == DV_DISK)
1373 printf(" %s[a-p]", dv->dv_xname);
1374#if defined(NFSCLIENT1)
1375 if (dv->dv_class == DV_IFNET)
1376 printf(" %s", dv->dv_xname);
1377#endif
1378 }
1379 printf("\n");
1380 }
1381 return (dv);
1382}
1383
1384struct device *
1385parsedisk(char *str, int len, int defpart, dev_t *devp)
1386{
1387 struct device *dv;
1388 int majdev, part = defpart;
1389 char c;
1390
1391 if (len == 0)
1392 return (NULL((void *)0));
1393 c = str[len-1];
1394 if (c >= 'a' && (c - 'a') < MAXPARTITIONS16) {
1395 part = c - 'a';
1396 len -= 1;
1397 }
1398
1399 TAILQ_FOREACH(dv, &alldevs, dv_list)for((dv) = ((&alldevs)->tqh_first); (dv) != ((void *)0
); (dv) = ((dv)->dv_list.tqe_next))
{
1400 if (dv->dv_class == DV_DISK &&
1401 strncmp(str, dv->dv_xname, len) == 0 &&
1402 dv->dv_xname[len] == '\0') {
1403 majdev = findblkmajor(dv);
1404 if (majdev < 0)
1405 return NULL((void *)0);
1406 *devp = MAKEDISKDEV(majdev, dv->dv_unit, part)(((dev_t)(((((majdev)) & 0xff) << 8) | ((((((dv->
dv_unit)) * 16) + ((part)))) & 0xff) | (((((((dv->dv_unit
)) * 16) + ((part)))) & 0xffff00) << 8))))
;
1407 break;
1408 }
1409#if defined(NFSCLIENT1)
1410 if (dv->dv_class == DV_IFNET &&
1411 strncmp(str, dv->dv_xname, len) == 0 &&
1412 dv->dv_xname[len] == '\0') {
1413 *devp = NODEV(dev_t)(-1);
1414 break;
1415 }
1416#endif
1417 }
1418
1419 return (dv);
1420}
1421
1422void
1423setroot(struct device *bootdv, int part, int exitflags)
1424{
1425 int majdev, unit, len, s, slept = 0;
1426 struct swdevt *swp;
1427 struct device *dv;
1428 dev_t nrootdev, nswapdev = NODEV(dev_t)(-1), temp = NODEV(dev_t)(-1);
1429 struct ifnet *ifp = NULL((void *)0);
1430 struct disk *dk;
1431 char buf[128];
1432#if defined(NFSCLIENT1)
1433 extern char *nfsbootdevname;
1434#endif
1435
1436 /* Ensure that all disk attach callbacks have completed. */
1437 do {
2
Loop condition is false. Exiting loop
1438 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
{
1
Assuming 'dk' is equal to null
1439 if (dk->dk_devno != NODEV(dev_t)(-1) &&
1440 (dk->dk_flags & DKF_OPENED0x0002) == 0) {
1441 tsleep_nsec(dk, 0, "dkopen", SEC_TO_NSEC(1));
1442 slept++;
1443 break;
1444 }
1445 }
1446 } while (dk
1.1
'dk' is equal to NULL
!= NULL((void *)0) && slept < 5);
1447
1448 if (slept
2.1
'slept' is not equal to 5
== 5) {
3
Taking false branch
1449 printf("disklabels not read:");
1450 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
1451 if (dk->dk_devno != NODEV(dev_t)(-1) &&
1452 (dk->dk_flags & DKF_OPENED0x0002) == 0)
1453 printf(" %s", dk->dk_name);
1454 printf("\n");
1455 }
1456
1457 if (duid_iszero(bootduid)) {
4
Taking true branch
1458 /* Locate DUID for boot disk since it was not provided. */
1459 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
5
Loop condition is false. Execution continues on line 1462
1460 if (dk->dk_device == bootdv)
1461 break;
1462 if (dk
5.1
'dk' is null
)
6
Taking false branch
1463 bcopy(dk->dk_label->d_uid, bootduid, sizeof(bootduid));
1464 } else if (bootdv == NULL((void *)0)) {
1465 /* Locate boot disk based on the provided DUID. */
1466 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
1467 if (duid_equal(dk->dk_label->d_uid, bootduid))
1468 break;
1469 if (dk)
1470 bootdv = dk->dk_device;
1471 }
1472 bcopy(bootduid, rootduid, sizeof(rootduid));
1473
1474#if NSOFTRAID1 > 0
1475 sr_map_root();
1476#endif
1477
1478 /*
1479 * If `swap generic' and we couldn't determine boot device,
1480 * ask the user.
1481 */
1482 dk = NULL((void *)0);
1483 if (mountroot == NULL((void *)0) && bootdv == NULL((void *)0))
7
Assuming 'mountroot' is not equal to NULL
1484 boothowto |= RB_ASKNAME0x00001;
1485 if (boothowto & RB_ASKNAME0x00001) {
8
Assuming the condition is false
9
Taking false branch
1486 while (1) {
1487 printf("root device");
1488 if (bootdv != NULL((void *)0)) {
1489 printf(" (default %s", bootdv->dv_xname);
1490 if (bootdv->dv_class == DV_DISK)
1491 printf("%c", 'a' + part);
1492 printf(")");
1493 }
1494 printf(": ");
1495 s = splhigh()splraise(0xd);
1496 cnpollc(1);
1497 len = getsn(buf, sizeof(buf));
1498 cnpollc(0);
1499 splx(s)spllower(s);
1500 if (strcmp(buf, "exit") == 0)
1501 reboot(exitflags);
1502 if (len == 0 && bootdv != NULL((void *)0)) {
1503 strlcpy(buf, bootdv->dv_xname, sizeof buf);
1504 len = strlen(buf);
1505 }
1506 if (len > 0 && buf[len - 1] == '*') {
1507 buf[--len] = '\0';
1508 dv = getdisk(buf, len, part, &nrootdev);
1509 if (dv != NULL((void *)0)) {
1510 rootdv = dv;
1511 nswapdev = nrootdev;
1512 goto gotswap;
1513 }
1514 }
1515 dv = getdisk(buf, len, part, &nrootdev);
1516 if (dv != NULL((void *)0)) {
1517 rootdv = dv;
1518 break;
1519 }
1520 }
1521
1522 if (rootdv->dv_class == DV_IFNET)
1523 goto gotswap;
1524
1525 /* try to build swap device out of new root device */
1526 while (1) {
1527 printf("swap device");
1528 if (rootdv != NULL((void *)0))
1529 printf(" (default %s%s)", rootdv->dv_xname,
1530 rootdv->dv_class == DV_DISK ? "b" : "");
1531 printf(": ");
1532 s = splhigh()splraise(0xd);
1533 cnpollc(1);
1534 len = getsn(buf, sizeof(buf));
1535 cnpollc(0);
1536 splx(s)spllower(s);
1537 if (strcmp(buf, "exit") == 0)
1538 reboot(exitflags);
1539 if (len == 0 && rootdv != NULL((void *)0)) {
1540 switch (rootdv->dv_class) {
1541 case DV_IFNET:
1542 nswapdev = NODEV(dev_t)(-1);
1543 break;
1544 case DV_DISK:
1545 nswapdev = MAKEDISKDEV(major(nrootdev),(((dev_t)((((((((unsigned)(nrootdev) >> 8) & 0xff))
) & 0xff) << 8) | (((((((((unsigned)((nrootdev) &
0xff) | (((nrootdev) & 0xffff0000) >> 8)) / 16))) *
16) + ((1)))) & 0xff) | ((((((((((unsigned)((nrootdev) &
0xff) | (((nrootdev) & 0xffff0000) >> 8)) / 16))) *
16) + ((1)))) & 0xffff00) << 8))))
1546 DISKUNIT(nrootdev), 1)(((dev_t)((((((((unsigned)(nrootdev) >> 8) & 0xff))
) & 0xff) << 8) | (((((((((unsigned)((nrootdev) &
0xff) | (((nrootdev) & 0xffff0000) >> 8)) / 16))) *
16) + ((1)))) & 0xff) | ((((((((((unsigned)((nrootdev) &
0xff) | (((nrootdev) & 0xffff0000) >> 8)) / 16))) *
16) + ((1)))) & 0xffff00) << 8))))
;
1547 if (nswapdev == nrootdev)
1548 continue;
1549 break;
1550 default:
1551 break;
1552 }
1553 break;
1554 }
1555 dv = getdisk(buf, len, 1, &nswapdev);
1556 if (dv) {
1557 if (dv->dv_class == DV_IFNET)
1558 nswapdev = NODEV(dev_t)(-1);
1559 if (nswapdev == nrootdev)
1560 continue;
1561 break;
1562 }
1563 }
1564gotswap:
1565 rootdev = nrootdev;
1566 dumpdev = nswapdev;
1567 swdevt[0].sw_dev = nswapdev;
1568 swdevt[1].sw_dev = NODEV(dev_t)(-1);
1569#if defined(NFSCLIENT1)
1570 } else if (mountroot == nfs_mountroot) {
10
Assuming 'mountroot' is equal to nfs_mountroot
11
Taking true branch
1571 rootdv = bootdv;
12
Value assigned to 'rootdv'
1572 rootdev = dumpdev = swapdev = NODEV(dev_t)(-1);
1573#endif
1574 } else if (mountroot == NULL((void *)0) && rootdev == NODEV(dev_t)(-1)) {
1575 /*
1576 * `swap generic'
1577 */
1578 rootdv = bootdv;
1579
1580 if (bootdv->dv_class == DV_DISK) {
1581 if (!duid_iszero(rootduid)) {
1582 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
1583 if (dk->dk_label && duid_equal(
1584 dk->dk_label->d_uid, rootduid))
1585 break;
1586 if (dk == NULL((void *)0))
1587 panic("root device (%s) not found",
1588 duid_format(rootduid));
1589 rootdv = dk->dk_device;
1590 }
1591 }
1592
1593 majdev = findblkmajor(rootdv);
1594 if (majdev >= 0) {
1595 /*
1596 * Root and swap are on the disk.
1597 * Assume swap is on partition b.
1598 */
1599 rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part)(((dev_t)(((((majdev)) & 0xff) << 8) | ((((((rootdv
->dv_unit)) * 16) + ((part)))) & 0xff) | (((((((rootdv
->dv_unit)) * 16) + ((part)))) & 0xffff00) << 8)
)))
;
1600 nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1)(((dev_t)(((((majdev)) & 0xff) << 8) | ((((((rootdv
->dv_unit)) * 16) + ((1)))) & 0xff) | (((((((rootdv->
dv_unit)) * 16) + ((1)))) & 0xffff00) << 8))))
;
1601 } else {
1602 /*
1603 * Root and swap are on a net.
1604 */
1605 nswapdev = NODEV(dev_t)(-1);
1606 }
1607 dumpdev = nswapdev;
1608 swdevt[0].sw_dev = nswapdev;
1609 /* swdevt[1].sw_dev = NODEV; */
1610 } else {
1611 /* Completely pre-configured, but we want rootdv .. */
1612 majdev = major(rootdev)(((unsigned)(rootdev) >> 8) & 0xff);
1613 if (findblkname(majdev) == NULL((void *)0))
1614 return;
1615 unit = DISKUNIT(rootdev)(((unsigned)((rootdev) & 0xff) | (((rootdev) & 0xffff0000
) >> 8)) / 16)
;
1616 part = DISKPART(rootdev)(((unsigned)((rootdev) & 0xff) | (((rootdev) & 0xffff0000
) >> 8)) % 16)
;
1617 snprintf(buf, sizeof buf, "%s%d%c",
1618 findblkname(majdev), unit, 'a' + part);
1619 rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
1620 if (rootdv == NULL((void *)0))
1621 panic("root device (%s) not found", buf);
1622 }
1623
1624 if (bootdv != NULL((void *)0) && bootdv->dv_class == DV_IFNET)
13
Assuming 'bootdv' is equal to NULL
1625 ifp = if_unit(bootdv->dv_xname);
1626
1627 if (ifp
13.1
'ifp' is null
) {
14
Taking false branch
1628 if_addgroup(ifp, "netboot");
1629 if_put(ifp);
1630 }
1631
1632 switch (rootdv->dv_class) {
15
Access to field 'dv_class' results in a dereference of a null pointer (loaded from variable 'rootdv')
1633#if defined(NFSCLIENT1)
1634 case DV_IFNET:
1635 mountroot = nfs_mountroot;
1636 nfsbootdevname = rootdv->dv_xname;
1637 return;
1638#endif
1639 case DV_DISK:
1640 mountroot = dk_mountroot;
1641 part = DISKPART(rootdev)(((unsigned)((rootdev) & 0xff) | (((rootdev) & 0xffff0000
) >> 8)) % 16)
;
1642 break;
1643 default:
1644 printf("can't figure root, hope your kernel is right\n");
1645 return;
1646 }
1647
1648 printf("root on %s%c", rootdv->dv_xname, 'a' + part);
1649
1650 if (dk && dk->dk_device == rootdv)
1651 printf(" (%s.%c)", duid_format(rootduid), 'a' + part);
1652
1653 /*
1654 * Make the swap partition on the root drive the primary swap.
1655 */
1656 for (swp = swdevt; swp->sw_dev != NODEV(dev_t)(-1); swp++) {
1657 if (major(rootdev)(((unsigned)(rootdev) >> 8) & 0xff) == major(swp->sw_dev)(((unsigned)(swp->sw_dev) >> 8) & 0xff) &&
1658 DISKUNIT(rootdev)(((unsigned)((rootdev) & 0xff) | (((rootdev) & 0xffff0000
) >> 8)) / 16)
== DISKUNIT(swp->sw_dev)(((unsigned)((swp->sw_dev) & 0xff) | (((swp->sw_dev
) & 0xffff0000) >> 8)) / 16)
) {
1659 temp = swdevt[0].sw_dev;
1660 swdevt[0].sw_dev = swp->sw_dev;
1661 swp->sw_dev = temp;
1662 break;
1663 }
1664 }
1665 if (swp->sw_dev != NODEV(dev_t)(-1)) {
1666 /*
1667 * If dumpdev was the same as the old primary swap device,
1668 * move it to the new primary swap device.
1669 */
1670 if (temp == dumpdev)
1671 dumpdev = swdevt[0].sw_dev;
1672 }
1673 if (swdevt[0].sw_dev != NODEV(dev_t)(-1))
1674 printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)(((unsigned)(swdevt[0].sw_dev) >> 8) & 0xff)),
1675 DISKUNIT(swdevt[0].sw_dev)(((unsigned)((swdevt[0].sw_dev) & 0xff) | (((swdevt[0].sw_dev
) & 0xffff0000) >> 8)) / 16)
,
1676 'a' + DISKPART(swdevt[0].sw_dev)(((unsigned)((swdevt[0].sw_dev) & 0xff) | (((swdevt[0].sw_dev
) & 0xffff0000) >> 8)) % 16)
);
1677 if (dumpdev != NODEV(dev_t)(-1))
1678 printf(" dump on %s%d%c", findblkname(major(dumpdev)(((unsigned)(dumpdev) >> 8) & 0xff)),
1679 DISKUNIT(dumpdev)(((unsigned)((dumpdev) & 0xff) | (((dumpdev) & 0xffff0000
) >> 8)) / 16)
, 'a' + DISKPART(dumpdev)(((unsigned)((dumpdev) & 0xff) | (((dumpdev) & 0xffff0000
) >> 8)) % 16)
);
1680 printf("\n");
1681}
1682
1683extern const struct nam2blk nam2blk[];
1684
1685int
1686findblkmajor(struct device *dv)
1687{
1688 char buf[16], *p;
1689 int i;
1690
1691 if (strlcpy(buf, dv->dv_xname, sizeof buf) >= sizeof buf)
1692 return (-1);
1693 for (p = buf; *p; p++)
1694 if (*p >= '0' && *p <= '9')
1695 *p = '\0';
1696
1697 for (i = 0; nam2blk[i].name; i++)
1698 if (!strcmp(buf, nam2blk[i].name))
1699 return (nam2blk[i].maj);
1700 return (-1);
1701}
1702
1703char *
1704findblkname(int maj)
1705{
1706 int i;
1707
1708 for (i = 0; nam2blk[i].name; i++)
1709 if (nam2blk[i].maj == maj)
1710 return (nam2blk[i].name);
1711 return (NULL((void *)0));
1712}
1713
1714char *
1715disk_readlabel(struct disklabel *dl, dev_t dev, char *errbuf, size_t errsize)
1716{
1717 struct vnode *vn;
1718 dev_t chrdev, rawdev;
1719 int error;
1720
1721 chrdev = blktochr(dev);
1722 rawdev = MAKEDISKDEV(major(chrdev), DISKUNIT(chrdev), RAW_PART)(((dev_t)((((((((unsigned)(chrdev) >> 8) & 0xff))) &
0xff) << 8) | (((((((((unsigned)((chrdev) & 0xff) |
(((chrdev) & 0xffff0000) >> 8)) / 16))) * 16) + ((
2)))) & 0xff) | ((((((((((unsigned)((chrdev) & 0xff) |
(((chrdev) & 0xffff0000) >> 8)) / 16))) * 16) + ((
2)))) & 0xffff00) << 8))))
;
1723
1724#ifdef DEBUG
1725 printf("dev=0x%x chrdev=0x%x rawdev=0x%x\n", dev, chrdev, rawdev);
1726#endif
1727
1728 if (cdevvp(rawdev, &vn)) {
1729 snprintf(errbuf, errsize,
1730 "cannot obtain vnode for 0x%x/0x%x", dev, rawdev);
1731 return (errbuf);
1732 }
1733
1734 error = VOP_OPEN(vn, FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1735 if (error) {
1736 snprintf(errbuf, errsize,
1737 "cannot open disk, 0x%x/0x%x, error %d",
1738 dev, rawdev, error);
1739 goto done;
1740 }
1741
1742 error = VOP_IOCTL(vn, DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) &
0x1fff) << 16) | ((('d')) << 8) | ((101)))
, (caddr_t)dl, FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1743 if (error) {
1744 snprintf(errbuf, errsize,
1745 "cannot read disk label, 0x%x/0x%x, error %d",
1746 dev, rawdev, error);
1747 }
1748done:
1749 VOP_CLOSE(vn, FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1750 vput(vn);
1751 if (error)
1752 return (errbuf);
1753 return (NULL((void *)0));
1754}
1755
1756int
1757disk_map(const char *path, char *mappath, int size, int flags)
1758{
1759 struct disk *dk, *mdk;
1760 u_char uid[8];
1761 char c, part;
1762 int i;
1763
1764 /*
1765 * Attempt to map a request for a disklabel UID to the correct device.
1766 * We should be supplied with a disklabel UID which has the following
1767 * format:
1768 *
1769 * [disklabel uid] . [partition]
1770 *
1771 * Alternatively, if the DM_OPENPART flag is set the disklabel UID can
1772 * based passed on its own.
1773 */
1774
1775 if (strchr(path, '/') != NULL((void *)0))
1776 return -1;
1777
1778 /* Verify that the device name is properly formed. */
1779 if (!((strlen(path) == 16 && (flags & DM_OPENPART0x1)) ||
1780 (strlen(path) == 18 && path[16] == '.')))
1781 return -1;
1782
1783 /* Get partition. */
1784 if (flags & DM_OPENPART0x1)
1785 part = 'a' + RAW_PART2;
1786 else
1787 part = path[17];
1788
1789 if (part < 'a' || part >= 'a' + MAXPARTITIONS16)
1790 return -1;
1791
1792 /* Derive label UID. */
1793 memset(uid, 0, sizeof(uid))__builtin_memset((uid), (0), (sizeof(uid)));
1794 for (i = 0; i < 16; i++) {
1795 c = path[i];
1796 if (c >= '0' && c <= '9')
1797 c -= '0';
1798 else if (c >= 'a' && c <= 'f')
1799 c -= ('a' - 10);
1800 else
1801 return -1;
1802
1803 uid[i / 2] <<= 4;
1804 uid[i / 2] |= c & 0xf;
1805 }
1806
1807 mdk = NULL((void *)0);
1808 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
{
1809 if (dk->dk_label && memcmp(dk->dk_label->d_uid, uid,__builtin_memcmp((dk->dk_label->d_uid), (uid), (sizeof(
dk->dk_label->d_uid)))
1810 sizeof(dk->dk_label->d_uid))__builtin_memcmp((dk->dk_label->d_uid), (uid), (sizeof(
dk->dk_label->d_uid)))
== 0) {
1811 /* Fail if there are duplicate UIDs! */
1812 if (mdk != NULL((void *)0))
1813 return -1;
1814 mdk = dk;
1815 }
1816 }
1817
1818 if (mdk == NULL((void *)0) || mdk->dk_name == NULL((void *)0))
1819 return -1;
1820
1821 snprintf(mappath, size, "/dev/%s%s%c",
1822 (flags & DM_OPENBLCK0x2) ? "" : "r", mdk->dk_name, part);
1823
1824 return 0;
1825}
1826
1827/*
1828 * Lookup a disk device and verify that it has completed attaching.
1829 */
1830struct device *
1831disk_lookup(struct cfdriver *cd, int unit)
1832{
1833 struct device *dv;
1834 struct disk *dk;
1835
1836 dv = device_lookup(cd, unit);
1837 if (dv == NULL((void *)0))
1838 return (NULL((void *)0));
1839
1840 TAILQ_FOREACH(dk, &disklist, dk_link)for((dk) = ((&disklist)->tqh_first); (dk) != ((void *)
0); (dk) = ((dk)->dk_link.tqe_next))
1841 if (dk->dk_device == dv)
1842 break;
1843
1844 if (dk == NULL((void *)0)) {
1845 device_unref(dv);
1846 return (NULL((void *)0));
1847 }
1848
1849 return (dv);
1850}
1851
1852int
1853duid_equal(u_char *duid1, u_char *duid2)
1854{
1855 return (memcmp(duid1, duid2, DUID_SIZE)__builtin_memcmp((duid1), (duid2), (8)) == 0);
1856}
1857
1858int
1859duid_iszero(u_char *duid)
1860{
1861 u_char zeroduid[DUID_SIZE8];
1862
1863 memset(zeroduid, 0, sizeof(zeroduid))__builtin_memset((zeroduid), (0), (sizeof(zeroduid)));
1864
1865 return (duid_equal(duid, zeroduid));
1866}
1867
1868const char *
1869duid_format(u_char *duid)
1870{
1871 static char duid_str[17];
1872
1873 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/subr_disk.c"
, 1873, "_kernel_lock_held()"))
;
1874
1875 snprintf(duid_str, sizeof(duid_str),
1876 "%02x%02x%02x%02x%02x%02x%02x%02x",
1877 duid[0], duid[1], duid[2], duid[3],
1878 duid[4], duid[5], duid[6], duid[7]);
1879
1880 return (duid_str);
1881}