geom_sunlabel_enc.c revision 256281
1/*- 2 * Copyright (c) 2003 Jake Burkholder 3 * Copyright (c) 2003 Poul-Henning Kamp 4 * Copyright (c) 2004,2005 Joerg Wunsch 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/* Functions to encode or decode struct sun_disklabel into a bytestream 29 * of correct endianess and packing. 30 * 31 * NB! This file must be usable both in kernel and userland. 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/10/sys/geom/geom_sunlabel_enc.c 144328 2005-03-30 09:33:10Z joerg $"); 36 37#include <sys/types.h> 38#include <sys/endian.h> 39#include <sys/errno.h> 40#include <sys/sun_disklabel.h> 41#ifdef _KERNEL 42#include <sys/systm.h> 43#else 44#include <string.h> 45#endif 46 47#define SL_TEXT 0x0 48#define SL_TEXT_SIZEOF 0x80 49#define SL_VTOC_VERS 0x80 50#define SL_VTOC_VOLNAME 0x84 51#define SL_VTOC_NPART 0x8c 52#define SL_VTOC_MAP 0x8e 53#define SL_VTOC_SANITY 0xbc 54#define SL_RPM 0x1a4 55#define SL_PCYLINDERS 0x1a6 56#define SL_SPARESPERCYL 0x1a8 57#define SL_INTERLEAVE 0x1ae 58#define SL_NCYLINDERS 0x1b0 59#define SL_ACYLINDERS 0x1b2 60#define SL_NTRACKS 0x1b4 61#define SL_NSECTORS 0x1b6 62#define SL_PART 0x1bc 63#define SL_MAGIC 0x1fc 64#define SL_CKSUM 0x1fe 65 66#define SDKP_CYLOFFSET 0 67#define SDKP_NSECTORS 0x4 68#define SDKP_SIZEOF 0x8 /* size of a partition entry */ 69 70#define SVTOC_TAG 0 71#define SVTOC_FLAG 0x2 72#define SVTOC_SIZEOF 0x4 /* size of a VTOC tag/flag entry */ 73 74/* 75 * Decode the relevant fields of a sun disk label, and return zero if the 76 * magic and checksum works out OK. 77 */ 78int 79sunlabel_dec(void const *pp, struct sun_disklabel *sl) 80{ 81 const uint8_t *p; 82 size_t i; 83 u_int u; 84 uint32_t vtocsane; 85 uint16_t npart; 86 87 p = pp; 88 for (i = 0; i < sizeof(sl->sl_text); i++) 89 sl->sl_text[i] = p[SL_TEXT + i]; 90 sl->sl_rpm = be16dec(p + SL_RPM); 91 sl->sl_pcylinders = be16dec(p + SL_PCYLINDERS); 92 sl->sl_sparespercyl = be16dec(p + SL_SPARESPERCYL); 93 sl->sl_interleave = be16dec(p + SL_INTERLEAVE); 94 sl->sl_ncylinders = be16dec(p + SL_NCYLINDERS); 95 sl->sl_acylinders = be16dec(p + SL_ACYLINDERS); 96 sl->sl_ntracks = be16dec(p + SL_NTRACKS); 97 sl->sl_nsectors = be16dec(p + SL_NSECTORS); 98 for (i = 0; i < SUN_NPART; i++) { 99 sl->sl_part[i].sdkp_cyloffset = be32dec(p + SL_PART + 100 (i * SDKP_SIZEOF) + SDKP_CYLOFFSET); 101 sl->sl_part[i].sdkp_nsectors = be32dec(p + SL_PART + 102 (i * SDKP_SIZEOF) + SDKP_NSECTORS); 103 } 104 sl->sl_magic = be16dec(p + SL_MAGIC); 105 vtocsane = be32dec(p + SL_VTOC_SANITY); 106 npart = be16dec(p + SL_VTOC_NPART); 107 if (vtocsane == SUN_VTOC_SANE && npart == SUN_NPART) { 108 /* 109 * Seems we've got SVR4-compatible VTOC information 110 * as well, decode it. 111 */ 112 sl->sl_vtoc_sane = vtocsane; 113 sl->sl_vtoc_vers = be32dec(p + SL_VTOC_VERS); 114 memcpy(sl->sl_vtoc_volname, p + SL_VTOC_VOLNAME, 115 SUN_VOLNAME_LEN); 116 sl->sl_vtoc_nparts = SUN_NPART; 117 for (i = 0; i < SUN_NPART; i++) { 118 sl->sl_vtoc_map[i].svtoc_tag = be16dec(p + 119 SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_TAG); 120 sl->sl_vtoc_map[i].svtoc_flag = be16dec(p + 121 SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_FLAG); 122 } 123 } 124 for (i = u = 0; i < SUN_SIZE; i += 2) 125 u ^= be16dec(p + i); 126 if (u == 0 && sl->sl_magic == SUN_DKMAGIC) 127 return (0); 128 else 129 return (EINVAL); 130} 131 132/* 133 * Encode the relevant fields into a sun disklabel, compute new checksum. 134 */ 135void 136sunlabel_enc(void *pp, struct sun_disklabel *sl) 137{ 138 uint8_t *p; 139 size_t i; 140 u_int u; 141 142 p = pp; 143 for (i = 0; i < SL_TEXT_SIZEOF; i++) 144 p[SL_TEXT + i] = sl->sl_text[i]; 145 be16enc(p + SL_RPM, sl->sl_rpm); 146 be16enc(p + SL_PCYLINDERS, sl->sl_pcylinders); 147 be16enc(p + SL_SPARESPERCYL, sl->sl_sparespercyl); 148 be16enc(p + SL_INTERLEAVE, sl->sl_interleave); 149 be16enc(p + SL_NCYLINDERS, sl->sl_ncylinders); 150 be16enc(p + SL_ACYLINDERS, sl->sl_acylinders); 151 be16enc(p + SL_NTRACKS, sl->sl_ntracks); 152 be16enc(p + SL_NSECTORS, sl->sl_nsectors); 153 for (i = 0; i < SUN_NPART; i++) { 154 be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_CYLOFFSET, 155 sl->sl_part[i].sdkp_cyloffset); 156 be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_NSECTORS, 157 sl->sl_part[i].sdkp_nsectors); 158 } 159 be16enc(p + SL_MAGIC, sl->sl_magic); 160 if (sl->sl_vtoc_sane == SUN_VTOC_SANE 161 && sl->sl_vtoc_nparts == SUN_NPART) { 162 /* 163 * Write SVR4-compatible VTOC elements. 164 */ 165 be32enc(p + SL_VTOC_VERS, sl->sl_vtoc_vers); 166 be32enc(p + SL_VTOC_SANITY, SUN_VTOC_SANE); 167 memcpy(p + SL_VTOC_VOLNAME, sl->sl_vtoc_volname, 168 SUN_VOLNAME_LEN); 169 be16enc(p + SL_VTOC_NPART, SUN_NPART); 170 for (i = 0; i < SUN_NPART; i++) { 171 be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 172 + SVTOC_TAG, 173 sl->sl_vtoc_map[i].svtoc_tag); 174 be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 175 + SVTOC_FLAG, 176 sl->sl_vtoc_map[i].svtoc_flag); 177 } 178 } 179 for (i = u = 0; i < SUN_SIZE; i += 2) 180 u ^= be16dec(p + i); 181 be16enc(p + SL_CKSUM, u); 182} 183