geom_sunlabel_enc.c revision 129963
1/*- 2 * Copyright (c) 2003 Jake Burkholder 3 * Copyright (c) 2003 Poul-Henning Kamp 4 * Copyright (c) 2004 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: head/sys/geom/geom_sunlabel_enc.c 129963 2004-06-01 20:18:25Z joerg $"); 36 37#include <sys/types.h> 38#include <sys/endian.h> 39#include <sys/errno.h> 40#include <sys/sun_disklabel.h> 41 42#define SL_TEXT 0x0 43#define SL_TEXT_SIZEOF 0x80 44#define SL_VTOC_VERS 0x80 45#define SL_VTOC_NPART 0x8c 46#define SL_VTOC_MAP 0x8e 47#define SL_VTOC_SANITY 0xbc 48#define SL_RPM 0x1a4 49#define SL_PCYLINDERS 0x1a6 50#define SL_SPARESPERCYL 0x1a8 51#define SL_INTERLEAVE 0x1ae 52#define SL_NCYLINDERS 0x1b0 53#define SL_ACYLINDERS 0x1b2 54#define SL_NTRACKS 0x1b4 55#define SL_NSECTORS 0x1b6 56#define SL_PART 0x1bc 57#define SL_MAGIC 0x1fc 58#define SL_CKSUM 0x1fe 59 60#define SDKP_CYLOFFSET 0 61#define SDKP_NSECTORS 0x4 62#define SDKP_SIZEOF 0x8 /* size of a partition entry */ 63 64#define SVTOC_TAG 0 65#define SVTOC_FLAG 0x2 66#define SVTOC_SIZEOF 0x4 /* size of a VTOC tag/flag entry */ 67 68/* 69 * Decode the relevant fields of a sun disk label, and return zero if the 70 * magic and checksum works out OK. 71 */ 72int 73sunlabel_dec(void const *pp, struct sun_disklabel *sl) 74{ 75 const uint8_t *p; 76 size_t i; 77 u_int u; 78 uint32_t vtocsane; 79 uint16_t npart; 80 81 p = pp; 82 for (i = 0; i < sizeof(sl->sl_text); i++) 83 sl->sl_text[i] = p[SL_TEXT + i]; 84 sl->sl_rpm = be16dec(p + SL_RPM); 85 sl->sl_pcylinders = be16dec(p + SL_PCYLINDERS); 86 sl->sl_sparespercyl = be16dec(p + SL_SPARESPERCYL); 87 sl->sl_interleave = be16dec(p + SL_INTERLEAVE); 88 sl->sl_ncylinders = be16dec(p + SL_NCYLINDERS); 89 sl->sl_acylinders = be16dec(p + SL_ACYLINDERS); 90 sl->sl_ntracks = be16dec(p + SL_NTRACKS); 91 sl->sl_nsectors = be16dec(p + SL_NSECTORS); 92 for (i = 0; i < SUN_NPART; i++) { 93 sl->sl_part[i].sdkp_cyloffset = be32dec(p + SL_PART + 94 (i * SDKP_SIZEOF) + SDKP_CYLOFFSET); 95 sl->sl_part[i].sdkp_nsectors = be32dec(p + SL_PART + 96 (i * SDKP_SIZEOF) + SDKP_NSECTORS); 97 } 98 sl->sl_magic = be16dec(p + SL_MAGIC); 99 vtocsane = be32dec(p + SL_VTOC_SANITY); 100 npart = be16dec(p + SL_VTOC_NPART); 101 if (vtocsane == SUN_VTOC_SANE && npart == SUN_NPART) { 102 /* 103 * Seems we've got SVR4-compatible VTOC information 104 * as well, decode it. 105 */ 106 sl->sl_vtoc_sane = vtocsane; 107 sl->sl_vtoc_vers = be32dec(p + SL_VTOC_VERS); 108 sl->sl_vtoc_nparts = SUN_NPART; 109 for (i = 0; i < SUN_NPART; i++) { 110 sl->sl_vtoc_map[i].svtoc_tag = be16dec(p + 111 SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_TAG); 112 sl->sl_vtoc_map[i].svtoc_flag = be16dec(p + 113 SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_FLAG); 114 } 115 } 116 for (i = u = 0; i < SUN_SIZE; i += 2) 117 u ^= be16dec(p + i); 118 if (u == 0 && sl->sl_magic == SUN_DKMAGIC) 119 return (0); 120 else 121 return (EINVAL); 122} 123 124/* 125 * Encode the relevant fields into a sun disklabel, compute new checksum. 126 */ 127void 128sunlabel_enc(void *pp, struct sun_disklabel *sl) 129{ 130 uint8_t *p; 131 size_t i; 132 u_int u; 133 134 p = pp; 135 for (i = 0; i < SL_TEXT_SIZEOF; i++) 136 p[SL_TEXT + i] = sl->sl_text[i]; 137 be16enc(p + SL_RPM, sl->sl_rpm); 138 be16enc(p + SL_PCYLINDERS, sl->sl_pcylinders); 139 be16enc(p + SL_SPARESPERCYL, sl->sl_sparespercyl); 140 be16enc(p + SL_INTERLEAVE, sl->sl_interleave); 141 be16enc(p + SL_NCYLINDERS, sl->sl_ncylinders); 142 be16enc(p + SL_ACYLINDERS, sl->sl_acylinders); 143 be16enc(p + SL_NTRACKS, sl->sl_ntracks); 144 be16enc(p + SL_NSECTORS, sl->sl_nsectors); 145 for (i = 0; i < SUN_NPART; i++) { 146 be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_CYLOFFSET, 147 sl->sl_part[i].sdkp_cyloffset); 148 be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_NSECTORS, 149 sl->sl_part[i].sdkp_nsectors); 150 } 151 be16enc(p + SL_MAGIC, sl->sl_magic); 152 if (sl->sl_vtoc_sane == SUN_VTOC_SANE 153 && sl->sl_vtoc_nparts == SUN_NPART) { 154 /* 155 * Write SVR4-compatible VTOC elements. 156 */ 157 be32enc(p + SL_VTOC_VERS, sl->sl_vtoc_vers); 158 be32enc(p + SL_VTOC_SANITY, SUN_VTOC_SANE); 159 be16enc(p + SL_VTOC_NPART, SUN_NPART); 160 for (i = 0; i < SUN_NPART; i++) { 161 be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 162 + SVTOC_TAG, 163 sl->sl_vtoc_map[i].svtoc_tag); 164 be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 165 + SVTOC_FLAG, 166 sl->sl_vtoc_map[i].svtoc_flag); 167 } 168 } 169 for (i = u = 0; i < SUN_SIZE; i += 2) 170 u ^= be16dec(p + i); 171 be16enc(p + SL_CKSUM, u); 172} 173