1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 24 * 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 28 * Copyright 2016 Toomas Soome <tsoome@me.com> 29 */ 30 31 32 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 33 /* All Rights Reserved */ 34 35 36 #ifndef _SYS_VTOC_H 37 #define _SYS_VTOC_H 38 39 #include <sys/dklabel.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /* 46 * Note: the VTOC is not implemented fully, nor in the manner 47 * that AT&T implements it. AT&T puts the vtoc structure 48 * into a sector, usually the second sector (pdsector is first). 49 * 50 * Sun incorporates the tag, flag, version, and volume vtoc fields into 51 * its Disk Label, which already has some vtoc-equivalent fields. 52 * Upon reading the vtoc with read_vtoc(), the following exceptions 53 * occur: 54 * v_bootinfo [all] returned as zero 55 * v_sanity returned as VTOC_SANE 56 * if Disk Label was sane 57 * v_sectorsz returned as 512 58 * v_reserved [all] retunred as zero 59 * timestamp [all] returned as zero 60 * 61 * See dklabel.h, read_vtoc(), and write_vtoc(). 62 */ 63 64 #define V_NUMPAR NDKMAP /* The number of partitions */ 65 /* (from dkio.h) */ 66 67 #define VTOC_SANE 0x600DDEEE /* Indicates a sane VTOC */ 68 #define V_VERSION 0x01 /* layout version number */ 69 #define V_EXTVERSION V_VERSION /* extvtoc layout version number */ 70 71 /* 72 * Partition identification tags 73 */ 74 #define V_UNASSIGNED 0x00 /* unassigned partition */ 75 #define V_BOOT 0x01 /* Boot partition */ 76 #define V_ROOT 0x02 /* Root filesystem */ 77 #define V_SWAP 0x03 /* Swap filesystem */ 78 #define V_USR 0x04 /* Usr filesystem */ 79 #define V_BACKUP 0x05 /* full disk */ 80 #define V_STAND 0x06 /* Stand partition */ 81 #define V_VAR 0x07 /* Var partition */ 82 #define V_HOME 0x08 /* Home partition */ 83 #define V_ALTSCTR 0x09 /* Alternate sector partition */ 84 #define V_CACHE 0x0a /* CacheFS partition (obsolete) */ 85 86 /* Tags for EFI/GPT labels */ 87 #define V_RESERVED 0x0b /* SMI reserved data */ 88 #define V_SYSTEM 0x0c /* EFI/GPT system partition */ 89 90 #define V_VXVM_PUB 0x0e /* VxVM public region */ 91 #define V_VXVM_PRIV 0x0f /* VxVM private region */ 92 93 #define V_BIOS_BOOT 0x18 /* Grub2 BIOS Boot partition */ 94 95 /* NetBSD/mips defines this */ 96 #define V_NETBSD_FFS 0xff 97 98 /* FreeBSD tags: the high byte equals ELFOSABI_FREEBSD */ 99 #define V_FREEBSD_BOOT 0x0900 100 #define V_FREEBSD_SWAP 0x0901 101 #define V_FREEBSD_UFS 0x0902 102 #define V_FREEBSD_VINUM 0x0903 103 #define V_FREEBSD_ZFS 0x0904 104 #define V_FREEBSD_NANDFS 0x0905 105 106 #define V_UNKNOWN 0xffff /* Unknown partition */ 107 108 /* 109 * Partition permission flags 110 */ 111 #define V_UNMNT 0x01 /* Unmountable partition */ 112 #define V_RONLY 0x10 /* Read only */ 113 114 /* 115 * error codes for reading & writing vtoc 116 */ 117 #define VT_ERROR (-2) /* errno supplies specific error */ 118 #define VT_EIO (-3) /* I/O error accessing vtoc */ 119 #define VT_EINVAL (-4) /* illegal value in vtoc or request */ 120 #define VT_ENOTSUP (-5) /* VTOC op. not supported */ 121 #define VT_ENOSPC (-6) /* requested space not found */ 122 #define VT_EOVERFLOW (-7) /* VTOC op. data struct limited */ 123 124 struct partition { 125 ushort_t p_tag; /* ID tag of partition */ 126 ushort_t p_flag; /* permission flags */ 127 daddr_t p_start; /* start sector no of partition */ 128 long p_size; /* # of blocks in partition */ 129 }; 130 131 struct vtoc { 132 unsigned long v_bootinfo[3]; /* info needed by mboot (unsupported) */ 133 unsigned long v_sanity; /* to verify vtoc sanity */ 134 unsigned long v_version; /* layout version */ 135 char v_volume[LEN_DKL_VVOL]; /* volume name */ 136 ushort_t v_sectorsz; /* sector size in bytes */ 137 ushort_t v_nparts; /* number of partitions */ 138 unsigned long v_reserved[10]; /* free space */ 139 struct partition v_part[V_NUMPAR]; /* partition headers */ 140 time_t timestamp[V_NUMPAR]; /* partition timestamp (unsupported) */ 141 char v_asciilabel[LEN_DKL_ASCII]; /* for compatibility */ 142 }; 143 144 struct extpartition { 145 ushort_t p_tag; /* ID tag of partition */ 146 ushort_t p_flag; /* permission flags */ 147 ushort_t p_pad[2]; 148 diskaddr_t p_start; /* start sector no of partition */ 149 diskaddr_t p_size; /* # of blocks in partition */ 150 }; 151 152 153 struct extvtoc { 154 uint64_t v_bootinfo[3]; /* info needed by mboot (unsupported) */ 155 uint64_t v_sanity; /* to verify vtoc sanity */ 156 uint64_t v_version; /* layout version */ 157 char v_volume[LEN_DKL_VVOL]; /* volume name */ 158 ushort_t v_sectorsz; /* sector size in bytes */ 159 ushort_t v_nparts; /* number of partitions */ 160 ushort_t pad[2]; 161 uint64_t v_reserved[10]; 162 struct extpartition v_part[V_NUMPAR]; /* partition headers */ 163 uint64_t timestamp[V_NUMPAR]; /* partition timestamp (unsupported) */ 164 char v_asciilabel[LEN_DKL_ASCII]; /* for compatibility */ 165 }; 166 167 #ifdef _KERNEL 168 #define extvtoctovtoc(extv, v) \ 169 { \ 170 int i; \ 171 v.v_bootinfo[0] = (unsigned long)extv.v_bootinfo[0]; \ 172 v.v_bootinfo[1] = (unsigned long)extv.v_bootinfo[1]; \ 173 v.v_bootinfo[2] = (unsigned long)extv.v_bootinfo[2]; \ 174 v.v_sanity = (unsigned long)extv.v_sanity; \ 175 v.v_version = (unsigned long)extv.v_version; \ 176 bcopy(extv.v_volume, v.v_volume, LEN_DKL_VVOL); \ 177 v.v_sectorsz = extv.v_sectorsz; \ 178 v.v_nparts = extv.v_nparts; \ 179 for (i = 0; i < 10; i++) \ 180 v.v_reserved[i] = (unsigned long)extv.v_reserved[i]; \ 181 for (i = 0; i < V_NUMPAR; i++) { \ 182 v.v_part[i].p_tag = extv.v_part[i].p_tag; \ 183 v.v_part[i].p_flag = extv.v_part[i].p_flag; \ 184 v.v_part[i].p_start = (daddr_t)extv.v_part[i].p_start; \ 185 v.v_part[i].p_size = (long)extv.v_part[i].p_size; \ 186 v.timestamp[i] = (time_t)extv.timestamp[i]; \ 187 } \ 188 bcopy(extv.v_asciilabel, v.v_asciilabel, LEN_DKL_ASCII); \ 189 } 190 191 #define vtoctoextvtoc(v, extv) \ 192 { \ 193 int i; \ 194 extv.v_bootinfo[0] = (uint64_t)v.v_bootinfo[0]; \ 195 extv.v_bootinfo[1] = (uint64_t)v.v_bootinfo[1]; \ 196 extv.v_bootinfo[2] = (uint64_t)v.v_bootinfo[2]; \ 197 extv.v_sanity = (uint64_t)v.v_sanity; \ 198 extv.v_version = (uint64_t)v.v_version; \ 199 bcopy(v.v_volume, extv.v_volume, LEN_DKL_VVOL); \ 200 extv.v_sectorsz = v.v_sectorsz; \ 201 extv.v_nparts = v.v_nparts; \ 202 for (i = 0; i < 10; i++) \ 203 extv.v_reserved[i] = (uint64_t)v.v_reserved[i]; \ 204 for (i = 0; i < V_NUMPAR; i++) { \ 205 extv.v_part[i].p_tag = v.v_part[i].p_tag; \ 206 extv.v_part[i].p_flag = v.v_part[i].p_flag; \ 207 extv.v_part[i].p_start = \ 208 (diskaddr_t)(unsigned long)v.v_part[i].p_start; \ 209 extv.v_part[i].p_size = \ 210 (diskaddr_t)(unsigned long)v.v_part[i].p_size; \ 211 extv.timestamp[i] = (uint64_t)v.timestamp[i]; \ 212 } \ 213 bcopy(v.v_asciilabel, extv.v_asciilabel, LEN_DKL_ASCII); \ 214 } 215 #endif /* _KERNEL */ 216 217 #if defined(_SYSCALL32) 218 struct partition32 { 219 uint16_t p_tag; /* ID tag of partition */ 220 uint16_t p_flag; /* permission flags */ 221 daddr32_t p_start; /* start sector no of partition */ 222 int32_t p_size; /* # of blocks in partition */ 223 }; 224 225 struct vtoc32 { 226 uint32_t v_bootinfo[3]; /* info needed by mboot (unsupported) */ 227 uint32_t v_sanity; /* to verify vtoc sanity */ 228 uint32_t v_version; /* layout version */ 229 char v_volume[LEN_DKL_VVOL]; /* volume name */ 230 uint16_t v_sectorsz; /* sector size in bytes */ 231 uint16_t v_nparts; /* number of partitions */ 232 uint32_t v_reserved[10]; /* free space */ 233 struct partition32 v_part[V_NUMPAR]; /* partition headers */ 234 time32_t timestamp[V_NUMPAR]; /* partition timestamp (unsupported) */ 235 char v_asciilabel[LEN_DKL_ASCII]; /* for compatibility */ 236 }; 237 238 #define vtoc32tovtoc(v32, v) \ 239 { \ 240 int i; \ 241 v.v_bootinfo[0] = v32.v_bootinfo[0]; \ 242 v.v_bootinfo[1] = v32.v_bootinfo[1]; \ 243 v.v_bootinfo[2] = v32.v_bootinfo[2]; \ 244 v.v_sanity = v32.v_sanity; \ 245 v.v_version = v32.v_version; \ 246 bcopy(v32.v_volume, v.v_volume, LEN_DKL_VVOL); \ 247 v.v_sectorsz = v32.v_sectorsz; \ 248 v.v_nparts = v32.v_nparts; \ 249 v.v_version = v32.v_version; \ 250 for (i = 0; i < 10; i++) \ 251 v.v_reserved[i] = v32.v_reserved[i]; \ 252 for (i = 0; i < V_NUMPAR; i++) { \ 253 v.v_part[i].p_tag = (ushort_t)v32.v_part[i].p_tag; \ 254 v.v_part[i].p_flag = (ushort_t)v32.v_part[i].p_flag; \ 255 v.v_part[i].p_start = (unsigned)v32.v_part[i].p_start; \ 256 v.v_part[i].p_size = (unsigned)v32.v_part[i].p_size; \ 257 } \ 258 for (i = 0; i < V_NUMPAR; i++) \ 259 v.timestamp[i] = (time_t)v32.timestamp[i]; \ 260 bcopy(v32.v_asciilabel, v.v_asciilabel, LEN_DKL_ASCII); \ 261 } 262 263 #define vtoc32toextvtoc(v32, extv) \ 264 { \ 265 int i; \ 266 extv.v_bootinfo[0] = v32.v_bootinfo[0]; \ 267 extv.v_bootinfo[1] = v32.v_bootinfo[1]; \ 268 extv.v_bootinfo[2] = v32.v_bootinfo[2]; \ 269 extv.v_sanity = v32.v_sanity; \ 270 extv.v_version = v32.v_version; \ 271 bcopy(v32.v_volume, extv.v_volume, LEN_DKL_VVOL); \ 272 extv.v_sectorsz = v32.v_sectorsz; \ 273 extv.v_nparts = v32.v_nparts; \ 274 extv.v_version = v32.v_version; \ 275 for (i = 0; i < 10; i++) \ 276 extv.v_reserved[i] = v32.v_reserved[i]; \ 277 for (i = 0; i < V_NUMPAR; i++) { \ 278 extv.v_part[i].p_tag = (ushort_t)v32.v_part[i].p_tag; \ 279 extv.v_part[i].p_flag = (ushort_t)v32.v_part[i].p_flag; \ 280 extv.v_part[i].p_start = (diskaddr_t)v32.v_part[i].p_start; \ 281 extv.v_part[i].p_size = (diskaddr_t)v32.v_part[i].p_size; \ 282 extv.timestamp[i] = (time_t)v32.timestamp[i]; \ 283 } \ 284 bcopy(v32.v_asciilabel, extv.v_asciilabel, LEN_DKL_ASCII); \ 285 } 286 287 288 #define vtoctovtoc32(v, v32) \ 289 { \ 290 int i; \ 291 v32.v_bootinfo[0] = (uint32_t)v.v_bootinfo[0]; \ 292 v32.v_bootinfo[1] = (uint32_t)v.v_bootinfo[1]; \ 293 v32.v_bootinfo[2] = (uint32_t)v.v_bootinfo[2]; \ 294 v32.v_sanity = (uint32_t)v.v_sanity; \ 295 v32.v_version = (uint32_t)v.v_version; \ 296 bcopy(v.v_volume, v32.v_volume, LEN_DKL_VVOL); \ 297 v32.v_sectorsz = v.v_sectorsz; \ 298 v32.v_nparts = v.v_nparts; \ 299 v32.v_version = (uint32_t)v.v_version; \ 300 for (i = 0; i < 10; i++) \ 301 v32.v_reserved[i] = v.v_reserved[i]; \ 302 for (i = 0; i < V_NUMPAR; i++) { \ 303 v32.v_part[i].p_tag = (ushort_t)v.v_part[i].p_tag; \ 304 v32.v_part[i].p_flag = (ushort_t)v.v_part[i].p_flag; \ 305 v32.v_part[i].p_start = (unsigned)v.v_part[i].p_start; \ 306 v32.v_part[i].p_size = (unsigned)v.v_part[i].p_size; \ 307 } \ 308 for (i = 0; i < V_NUMPAR; i++) { \ 309 if (v.timestamp[i] > TIME32_MAX) \ 310 v32.timestamp[i] = TIME32_MAX; \ 311 else \ 312 v32.timestamp[i] = (time32_t)v.timestamp[i]; \ 313 } \ 314 bcopy(v.v_asciilabel, v32.v_asciilabel, LEN_DKL_ASCII); \ 315 } 316 317 #define extvtoctovtoc32(extv, v32) \ 318 { \ 319 int i; \ 320 v32.v_bootinfo[0] = extv.v_bootinfo[0]; \ 321 v32.v_bootinfo[1] = extv.v_bootinfo[1]; \ 322 v32.v_bootinfo[2] = extv.v_bootinfo[2]; \ 323 v32.v_sanity = extv.v_sanity; \ 324 v32.v_version = extv.v_version; \ 325 bcopy(extv.v_volume, v32.v_volume, LEN_DKL_VVOL); \ 326 v32.v_sectorsz = extv.v_sectorsz; \ 327 v32.v_nparts = extv.v_nparts; \ 328 v32.v_version = extv.v_version; \ 329 for (i = 0; i < 10; i++) \ 330 v32.v_reserved[i] = extv.v_reserved[i]; \ 331 for (i = 0; i < V_NUMPAR; i++) { \ 332 v32.v_part[i].p_tag = (ushort_t)extv.v_part[i].p_tag; \ 333 v32.v_part[i].p_flag = (ushort_t)extv.v_part[i].p_flag; \ 334 v32.v_part[i].p_start = (unsigned)extv.v_part[i].p_start; \ 335 v32.v_part[i].p_size = (unsigned)extv.v_part[i].p_size; \ 336 } \ 337 for (i = 0; i < V_NUMPAR; i++) { \ 338 if (extv.timestamp[i] > TIME32_MAX) \ 339 v32.timestamp[i] = TIME32_MAX; \ 340 else \ 341 v32.timestamp[i] = (time32_t)extv.timestamp[i]; \ 342 } \ 343 bcopy(extv.v_asciilabel, v32.v_asciilabel, LEN_DKL_ASCII); \ 344 } 345 346 347 #endif /* _SYSCALL32 */ 348 349 /* 350 * These defines are the mode parameter for the checksum routines. 351 */ 352 #define CK_CHECKSUM 0 /* check checksum */ 353 #define CK_MAKESUM 1 /* generate checksum */ 354 355 extern int read_vtoc(int, struct vtoc *); 356 extern int write_vtoc(int, struct vtoc *); 357 extern int read_extvtoc(int, struct extvtoc *); 358 extern int write_extvtoc(int, struct extvtoc *); 359 360 #ifdef __cplusplus 361 } 362 #endif 363 364 #endif /* _SYS_VTOC_H */ 365