1/* $OpenBSD: disklabel.h,v 1.94 2025/11/13 20:59:14 deraadt Exp $ */
2/* $NetBSD: disklabel.h,v 1.41 1996/05/10 23:07:37 mark Exp $ */
3
4/*
5 * Copyright (c) 1987, 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)disklabel.h 8.2 (Berkeley) 7/10/94
33 */
34
35/*
36 * Disk description table, see disktab(5)
37 */
38#define _PATH_DISKTAB "/etc/disktab"
39#define DISKTAB "/etc/disktab" /* deprecated */
40
41/*
42 * Each disk has a label which includes information about the hardware
43 * disk geometry, filesystem partitions, and drive specific information.
44 * The location of the label, as well as the number of partitions the
45 * label can describe and the number of the "whole disk" (raw)
46 * partition are machine dependent.
47 */
48#include <machine/disklabel.h>
49
50#include <sys/uuid.h>
51
52/*
53 * The dev_t split has 64 partitions, but only 52 are visible
54 * and easily useable in userland (a-z and A-Z).
55 * The MD variable MAXPARTITIONS remains 52 (or less).
56 */
57#define MAXPARTITIONSUNIT 64
58
59/*
60 * Various situations still have structures limited to 16 partitions.
61 */
62#define MAXPARTITIONS16 16
63
64/*
65 * Translate between device numbers and major/disk unit/disk partition.
66 */
67#define DISKUNIT(dev) (minor(dev) / MAXPARTITIONSUNIT)
68#define DISKPART(dev) (minor(dev) % MAXPARTITIONSUNIT)
69#define RAW_PART 2 /* 'c' partition */
70#define DISKMINOR(unit, part) \
71 (((unit) * MAXPARTITIONSUNIT) + (part))
72#define MAKEDISKDEV(maj, unit, part) \
73 (makedev((maj), DISKMINOR((unit), (part))))
74#define DISKLABELDEV(dev) \
75 (MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART))
76
77#define DISKMAGIC 0x82564557U /* The disk magic number */
78
79#define MAXDISKSIZE 0x7fffffffffffLL /* 47 bits of reach */
80
81#ifndef _LOCORE
82struct disklabel {
83 u_int32_t d_magic; /* the magic number */
84 u_int16_t d_type; /* drive type */
85 u_int16_t d_subtype; /* controller/d_type specific */
86 char d_typename[16]; /* type name, e.g. "eagle" */
87 char d_packname[16]; /* pack identifier */
88
89 /* disk geometry: */
90 u_int32_t d_secsize; /* # of bytes per sector */
91 u_int32_t d_nsectors; /* # of data sectors per track */
92 u_int32_t d_ntracks; /* # of tracks per cylinder */
93 u_int32_t d_ncylinders; /* # of data cylinders per unit */
94 u_int32_t d_secpercyl; /* # of data sectors per cylinder */
95 u_int32_t d_secperunit; /* # of data sectors (low part) */
96
97 u_char d_uid[8]; /* Unique label identifier. */
98
99 /*
100 * Alternate cylinders include maintenance, replacement, configuration
101 * description areas, etc.
102 */
103 u_int32_t d_acylinders; /* # of alt. cylinders per unit */
104
105 /* hardware characteristics: */
106 u_int16_t d_bstarth; /* start of useable region (high part) */
107 u_int16_t d_bendh; /* size of useable region (high part) */
108 u_int32_t d_bstart; /* start of useable region */
109 u_int32_t d_bend; /* end of useable region */
110 u_int32_t d_flags; /* generic flags */
111#define NDDATA 5
112 u_int32_t d_spare4[NDDATA];
113 u_int16_t d_secperunith; /* # of data sectors (high part) */
114 u_int16_t d_version; /* version # (1=48 bit addressing) */
115#define NSPARE 4
116 u_int32_t d_spare[NSPARE]; /* reserved for future use */
117 u_int32_t d_magic2; /* the magic number (again) */
118 u_int16_t d_checksum; /* xor of data incl. partitions */
119
120 /* filesystem and partition information: */
121 u_int16_t d_npartitions; /* number of partitions in following */
122 u_int32_t d_spare2;
123 u_int32_t d_spare3;
124 struct partition { /* the partition table */
125 u_int32_t p_size; /* number of sectors (low part) */
126 u_int32_t p_offset; /* starting sector (low part) */
127 u_int16_t p_offseth; /* starting sector (high part) */
128 u_int16_t p_sizeh; /* number of sectors (high part) */
129 u_int8_t p_fstype; /* filesystem type, see below */
130 u_int8_t p_fragblock; /* encoded filesystem frag/block */
131 u_int16_t p_cpg; /* UFS: FS cylinders per group */
132 } d_partitions[MAXPARTITIONSUNIT]; /* maximum 52 in use */
133};
134#endif /* _LOCORE */
135
136
137#define DISKLABELV1_FFS_FRAGBLOCK(fsize, frag) \
138 ((fsize) * (frag) == 0 ? 0 : \
139 (((ffs((fsize) * (frag)) - 13) << 3) | (ffs(frag))))
140
141#define DISKLABELV1_FFS_BSIZE(i) ((i) == 0 ? 0 : (1 << (((i) >> 3) + 12)))
142#define DISKLABELV1_FFS_FRAG(i) ((i) == 0 ? 0 : (1 << (((i) & 0x07) - 1)))
143#define DISKLABELV1_FFS_FSIZE(i) (DISKLABELV1_FFS_FRAG(i) == 0 ? 0 : \
144 (DISKLABELV1_FFS_BSIZE(i) / DISKLABELV1_FFS_FRAG(i)))
145
146#define DL_GETPSIZE(p) (((u_int64_t)(p)->p_sizeh << 32) + (p)->p_size)
147#define DL_SETPSIZE(p, n) do { \
148 u_int64_t __x = (n); \
149 (p)->p_sizeh = __x >> 32; \
150 (p)->p_size = __x; \
151 } while (0)
152#define DL_GETPOFFSET(p) (((u_int64_t)(p)->p_offseth << 32) + (p)->p_offset)
153#define DL_SETPOFFSET(p, n) do { \
154 u_int64_t __x = (n); \
155 (p)->p_offseth = __x >> 32; \
156 (p)->p_offset = __x; \
157 } while (0)
158
159#define DL_GETDSIZE(d) (((u_int64_t)(d)->d_secperunith << 32) + \
160 (d)->d_secperunit)
161#define DL_SETDSIZE(d, n) do { \
162 u_int64_t __x = (n); \
163 (d)->d_secperunith = __x >> 32; \
164 (d)->d_secperunit = __x; \
165 } while (0)
166#define DL_GETBSTART(d) (((u_int64_t)(d)->d_bstarth << 32) + \
167 (d)->d_bstart)
168#define DL_SETBSTART(d, n) do { \
169 u_int64_t __x = (n); \
170 (d)->d_bstarth = __x >> 32; \
171 (d)->d_bstart = __x; \
172 } while (0)
173#define DL_GETBEND(d) (((u_int64_t)(d)->d_bendh << 32) + \
174 (d)->d_bend)
175#define DL_SETBEND(d, n) do { \
176 u_int64_t __x = (n); \
177 (d)->d_bendh = __x >> 32; \
178 (d)->d_bend = __x; \
179 } while (0)
180
181#define DL_BLKSPERSEC(d) ((d)->d_secsize / DEV_BSIZE)
182#define DL_SECTOBLK(d, n) ((n) * DL_BLKSPERSEC(d))
183#define DL_BLKTOSEC(d, n) ((n) / DL_BLKSPERSEC(d))
184#define DL_BLKOFFSET(d, n) (((n) % DL_BLKSPERSEC(d)) * DEV_BSIZE)
185
186static __inline char
187DL_PARTNUM2NAME(int partnum)
188{
189 if (partnum >= MAXPARTITIONS)
190 return -1;
191 if (partnum <= 'z' - 'a')
192 return 'a' + partnum;
193 else if (partnum - 26 <= 'Z' - 'A')
194 return 'A' + partnum - 26;
195 return -1;
196}
197
198static __inline int
199DL_PARTNAME2NUM(char partname)
200{
201 int partnum = -1;
202
203 if (partname >= 'a' && partname <= 'z')
204 partnum = partname - 'a';
205 else if (partname >= 'A' && partname <= 'Z')
206 partnum = partname - 'A' + 26;
207 if (partnum >= MAXPARTITIONS)
208 partnum = -1;
209 return partnum;
210}
211
212/* d_type values: */
213#define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
214#define DTYPE_MSCP 2 /* MSCP */
215#define DTYPE_DEC 3 /* other DEC (rk, rl) */
216#define DTYPE_SCSI 4 /* SCSI */
217#define DTYPE_ESDI 5 /* ESDI interface */
218#define DTYPE_ST506 6 /* ST506 etc. */
219#define DTYPE_HPIB 7 /* CS/80 on HP-IB */
220#define DTYPE_HPFL 8 /* HP Fiber-link */
221#define DTYPE_FLOPPY 10 /* floppy */
222#define DTYPE_CCD 11 /* was: concatenated disk device */
223#define DTYPE_VND 12 /* vnode pseudo-disk */
224#define DTYPE_ATAPI 13 /* ATAPI */
225#define DTYPE_RAID 14 /* was: RAIDframe */
226#define DTYPE_RDROOT 15 /* ram disk root */
227
228#ifdef DKTYPENAMES
229static const char * const dktypenames[] = {
230 "unknown",
231 "SMD",
232 "MSCP",
233 "old DEC",
234 "SCSI",
235 "ESDI",
236 "ST506",
237 "HP-IB",
238 "HP-FL",
239 "type 9",
240 "floppy",
241 "ccd", /* deprecated */
242 "vnd",
243 "ATAPI",
244 "RAID",
245 "rdroot",
246 NULL
247};
248#define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1)
249#endif
250
251/*
252 * Filesystem type and version.
253 * Used to interpret other filesystem-specific
254 * per-partition information.
255 */
256#define FS_UNUSED 0 /* unused */
257#define FS_SWAP 1 /* swap */
258#define FS_V6 2 /* Sixth Edition */
259#define FS_V7 3 /* Seventh Edition */
260#define FS_SYSV 4 /* System V */
261#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
262#define FS_V8 6 /* Eighth Edition, 4K blocks */
263#define FS_BSDFFS 7 /* 4.2BSD fast file system */
264#define FS_MSDOS 8 /* MSDOS file system */
265#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */
266#define FS_OTHER 10 /* in use, but unknown/unsupported */
267#define FS_HPFS 11 /* OS/2 high-performance file system */
268#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */
269#define FS_BOOT 13 /* partition contains bootstrap */
270#define FS_ADOS 14 /* AmigaDOS fast file system */
271#define FS_HFS 15 /* Macintosh HFS */
272#define FS_ADFS 16 /* Acorn Disk Filing System */
273#define FS_EXT2FS 17 /* ext2fs */
274#define FS_CCD 18 /* ccd component */
275#define FS_RAID 19 /* RAIDframe or softraid */
276#define FS_NTFS 20 /* Windows/NT file system */
277#define FS_UDF 21 /* UDF (DVD) filesystem */
278
279#ifdef DKTYPENAMES
280static const char * const fstypenames[] = {
281 "unused",
282 "swap",
283 "Version6",
284 "Version7",
285 "SystemV",
286 "4.1BSD",
287 "Eighth-Edition",
288 "4.2BSD",
289 "MSDOS",
290 "4.4LFS",
291 "unknown",
292 "HPFS",
293 "ISO9660",
294 "boot",
295 "ADOS",
296 "HFS",
297 "ADFS",
298 "ext2fs",
299 "ccd",
300 "RAID",
301 "NTFS",
302 "UDF",
303 NULL
304};
305
306/* Similar to the above, but used for things like the mount command. */
307static char *fstypesnames[] = {
308 "", /* 0 */
309 "", /* 1 */
310 "", /* 2 */
311 "", /* 3 */
312 "", /* 4 */
313 "", /* 5 */
314 "", /* 6 */
315 "ffs", /* 7 */
316 "msdos", /* 8 */
317 "lfs", /* 9 */
318 "", /* 10 */
319 "", /* 11 */
320 "cd9660", /* 12 */
321 "", /* 13 */
322 "ados", /* 14 */
323 "", /* 15 */
324 "", /* 16 */
325 "ext2fs", /* 17 */
326 "", /* 18 */
327 "", /* 19 */
328 "ntfs", /* 20 */
329 "udf", /* 21 */
330 NULL
331};
332
333#define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
334#endif
335
336/*
337 * flags shared by various drives:
338 */
339#define D_VENDOR 0x08 /* vendor disklabel */
340
341#ifndef _LOCORE
342/*
343 * Structure used internally to retrieve information about a partition
344 * on a disk.
345 */
346struct partinfo {
347 struct disklabel *disklab;
348 struct partition *part;
349};
350
351/* GUID partition table -- located at sector 1 of some disks. */
352#define GPTSECTOR 1 /* DOS boot block relative sector # */
353#define GPTSIGNATURE 0x5452415020494645LL
354 /* ASCII string "EFI PART" encoded as 64-bit */
355#define GPTREVISION 0x10000 /* GPT header version 1.0 */
356#define NGPTPARTITIONS 128
357#define GPTPARTATTR_REQUIRED (1ULL << 0)
358#define GPTPARTATTR_IGNORE (1ULL << 1)
359#define GPTPARTATTR_BOOTABLE (1ULL << 2)
360#define GPTPARTATTR_MS_READONLY (1ULL << 60)
361#define GPTPARTATTR_MS_SHADOW (1ULL << 61)
362#define GPTPARTATTR_MS_HIDDEN (1ULL << 62)
363#define GPTPARTATTR_MS_NOAUTOMOUNT (1ULL << 63)
364
365#define GPTMINHDRSIZE 92
366#define GPTMINPARTSIZE 128
367#define GPTPARTNAMESIZE 36
368
369/* all values in the GPT need to be little endian as per UEFI specification */
370struct gpt_header {
371 u_int64_t gh_sig; /* "EFI PART" */
372 u_int32_t gh_rev; /* GPT Version 1.0: 0x00000100 */
373 u_int32_t gh_size; /* Little-Endian */
374 u_int32_t gh_csum; /* CRC32: with this field as 0 */
375 u_int32_t gh_rsvd; /* always zero */
376 u_int64_t gh_lba_self; /* LBA of this header */
377 u_int64_t gh_lba_alt; /* LBA of alternate header */
378 u_int64_t gh_lba_start; /* first usable LBA */
379 u_int64_t gh_lba_end; /* last usable LBA */
380 struct uuid gh_guid; /* disk GUID used to identify the disk */
381 u_int64_t gh_part_lba; /* starting LBA of GPT partition entries */
382 u_int32_t gh_part_num; /* # of partition entries */
383 u_int32_t gh_part_size; /* size per entry, shall be 128*(2**n)
384 with n >= 0 */
385 u_int32_t gh_part_csum; /* CRC32 checksum of all partition entries:
386 * starts at gh_part_lba and is computed over
387 * a byte length of gh_part_num*gh_part_size */
388 /* the rest of the block is reserved by UEFI and must be zero */
389};
390
391struct gpt_partition {
392 struct uuid gp_type; /* partition type GUID */
393 struct uuid gp_guid; /* unique partition GUID */
394 u_int64_t gp_lba_start; /* starting LBA of this partition */
395 u_int64_t gp_lba_end; /* ending LBA of this partition, inclusive,
396 usually odd */
397 u_int64_t gp_attrs; /* attribute flags */
398 u_int16_t gp_name[GPTPARTNAMESIZE]; /* partition name, utf-16le */
399 /* the rest of the GPT partition entry, if any, is reserved by UEFI
400 and must be zero */
401};
402
403#define GPT_UUID_EFI_SYSTEM \
404 { 0xc1, 0x2a, 0x73, 0x28, 0xf8, 0x1f, 0x11, 0xd2, \
405 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }
406#define GPT_UUID_OPENBSD \
407 { 0x82, 0x4c, 0xc7, 0xa0, 0x36, 0xa8, 0x11, 0xe3, \
408 0x89, 0x0a, 0x95, 0x25, 0x19, 0xad, 0x3f, 0x61 }
409
410/* DOS partition table -- located at start of some disks. */
411#define DOS_LABELSECTOR 1
412#define DOSBBSECTOR 0 /* DOS boot block relative sector # */
413#define DOSPARTOFF 446
414#define DOSDISKOFF 444
415#define NDOSPART 4
416#define DOSACTIVE 0x80 /* active partition */
417
418#define DOSMBR_SIGNATURE (0xaa55)
419#define DOSMBR_SIGNATURE_OFF (0x1fe)
420
421/* Maximum number of Extended Boot Records (EBRs) to traverse. */
422#define DOS_MAXEBR 256
423
424struct dos_partition {
425 u_int8_t dp_flag; /* bootstrap flags */
426 u_int8_t dp_shd; /* starting head */
427 u_int8_t dp_ssect; /* starting sector */
428 u_int8_t dp_scyl; /* starting cylinder */
429 u_int8_t dp_typ; /* partition type (see below) */
430 u_int8_t dp_ehd; /* end head */
431 u_int8_t dp_esect; /* end sector */
432 u_int8_t dp_ecyl; /* end cylinder */
433 u_int32_t dp_start; /* absolute starting sector number */
434 u_int32_t dp_size; /* partition size in sectors */
435};
436
437/* Known DOS partition types. */
438#define DOSPTYP_UNUSED 0x00 /* Unused partition */
439#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */
440#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */
441#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */
442#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */
443#define DOSPTYP_NTFS 0x07 /* NTFS */
444#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */
445#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */
446#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */
447#define DOSPTYP_EXTENDL 0x0f /* Extended, LBA-mapped; (sub-partitions) */
448#define DOSPTYP_ONTRACK 0x54
449#define DOSPTYP_LINUX 0x83 /* That other thing */
450#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */
451#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */
452#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */
453#define DOSPTYP_EFI 0xee /* EFI Protective Partition */
454#define DOSPTYP_EFISYS 0xef /* EFI System Partition */
455
456struct dos_mbr {
457 u_int8_t dmbr_boot[DOSPARTOFF];
458 struct dos_partition dmbr_parts[NDOSPART];
459 u_int16_t dmbr_sign;
460} __packed;
461
462#ifdef _KERNEL
463void diskerr(struct buf *, char *, char *, int, int, struct disklabel *);
464u_int dkcksum(struct disklabel *);
465int initdisklabel(struct disklabel *);
466int checkdisklabel(dev_t, void *, struct disklabel *, u_int64_t, u_int64_t);
467int setdisklabel(struct disklabel *, struct disklabel *, u_int64_t);
468int readdisklabel(dev_t, void (*)(struct buf *), struct disklabel *, int);
469int writedisklabel(dev_t, void (*)(struct buf *), struct disklabel *);
470int bounds_check_with_label(struct buf *, struct disklabel *);
471int readdisksector(struct buf *, void (*)(struct buf *),
472 struct disklabel *, u_int64_t);
473int readdoslabel(struct buf *, void (*)(struct buf *),
474 struct disklabel *, daddr_t *, int);
475#ifdef CD9660
476int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
477 struct disklabel *lp);
478#endif
479#ifdef UDF
480int udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
481 struct disklabel *lp);
482#endif
483#endif
484#endif /* _LOCORE */
485
486#if !defined(_KERNEL) && !defined(_LOCORE)
487
488#include <sys/cdefs.h>
489
490__BEGIN_DECLS
491struct disklabel *getdiskbyname(const char *);
492__END_DECLS
493
494#endif