geom_sunlabel_enc.c revision 144328
1113813Sphk/*- 2113813Sphk * Copyright (c) 2003 Jake Burkholder 3113813Sphk * Copyright (c) 2003 Poul-Henning Kamp 4144328Sjoerg * Copyright (c) 2004,2005 Joerg Wunsch 5113813Sphk * All rights reserved. 6113813Sphk * 7113813Sphk * Redistribution and use in source and binary forms, with or without 8113813Sphk * modification, are permitted provided that the following conditions 9113813Sphk * are met: 10113813Sphk * 1. Redistributions of source code must retain the above copyright 11113813Sphk * notice, this list of conditions and the following disclaimer. 12113813Sphk * 2. Redistributions in binary form must reproduce the above copyright 13113813Sphk * notice, this list of conditions and the following disclaimer in the 14113813Sphk * documentation and/or other materials provided with the distribution. 15113813Sphk * 16113813Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17113813Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18113813Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19113813Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20113813Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21113813Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22113813Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23113813Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24113813Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25113813Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26113813Sphk * SUCH DAMAGE. 27139778Simp */ 28139778Simp/* Functions to encode or decode struct sun_disklabel into a bytestream 29113813Sphk * of correct endianess and packing. 30113813Sphk * 31113813Sphk * NB! This file must be usable both in kernel and userland. 32113813Sphk */ 33113813Sphk 34116196Sobrien#include <sys/cdefs.h> 35116196Sobrien__FBSDID("$FreeBSD: head/sys/geom/geom_sunlabel_enc.c 144328 2005-03-30 09:33:10Z joerg $"); 36116196Sobrien 37113813Sphk#include <sys/types.h> 38113813Sphk#include <sys/endian.h> 39113813Sphk#include <sys/errno.h> 40113813Sphk#include <sys/sun_disklabel.h> 41144328Sjoerg#ifdef _KERNEL 42144328Sjoerg#include <sys/systm.h> 43144328Sjoerg#else 44144328Sjoerg#include <string.h> 45144328Sjoerg#endif 46113813Sphk 47113813Sphk#define SL_TEXT 0x0 48113813Sphk#define SL_TEXT_SIZEOF 0x80 49129963Sjoerg#define SL_VTOC_VERS 0x80 50144328Sjoerg#define SL_VTOC_VOLNAME 0x84 51129963Sjoerg#define SL_VTOC_NPART 0x8c 52129963Sjoerg#define SL_VTOC_MAP 0x8e 53129963Sjoerg#define SL_VTOC_SANITY 0xbc 54113813Sphk#define SL_RPM 0x1a4 55113813Sphk#define SL_PCYLINDERS 0x1a6 56113813Sphk#define SL_SPARESPERCYL 0x1a8 57113813Sphk#define SL_INTERLEAVE 0x1ae 58113813Sphk#define SL_NCYLINDERS 0x1b0 59113813Sphk#define SL_ACYLINDERS 0x1b2 60113813Sphk#define SL_NTRACKS 0x1b4 61113813Sphk#define SL_NSECTORS 0x1b6 62113813Sphk#define SL_PART 0x1bc 63113813Sphk#define SL_MAGIC 0x1fc 64113813Sphk#define SL_CKSUM 0x1fe 65113813Sphk 66113813Sphk#define SDKP_CYLOFFSET 0 67113813Sphk#define SDKP_NSECTORS 0x4 68129963Sjoerg#define SDKP_SIZEOF 0x8 /* size of a partition entry */ 69113813Sphk 70129963Sjoerg#define SVTOC_TAG 0 71129963Sjoerg#define SVTOC_FLAG 0x2 72129963Sjoerg#define SVTOC_SIZEOF 0x4 /* size of a VTOC tag/flag entry */ 73129963Sjoerg 74113813Sphk/* 75113813Sphk * Decode the relevant fields of a sun disk label, and return zero if the 76113813Sphk * magic and checksum works out OK. 77113813Sphk */ 78113813Sphkint 79113813Sphksunlabel_dec(void const *pp, struct sun_disklabel *sl) 80113813Sphk{ 81113813Sphk const uint8_t *p; 82113813Sphk size_t i; 83113813Sphk u_int u; 84129963Sjoerg uint32_t vtocsane; 85129963Sjoerg uint16_t npart; 86113813Sphk 87113813Sphk p = pp; 88113813Sphk for (i = 0; i < sizeof(sl->sl_text); i++) 89113813Sphk sl->sl_text[i] = p[SL_TEXT + i]; 90113813Sphk sl->sl_rpm = be16dec(p + SL_RPM); 91113813Sphk sl->sl_pcylinders = be16dec(p + SL_PCYLINDERS); 92113813Sphk sl->sl_sparespercyl = be16dec(p + SL_SPARESPERCYL); 93113813Sphk sl->sl_interleave = be16dec(p + SL_INTERLEAVE); 94113813Sphk sl->sl_ncylinders = be16dec(p + SL_NCYLINDERS); 95113813Sphk sl->sl_acylinders = be16dec(p + SL_ACYLINDERS); 96113813Sphk sl->sl_ntracks = be16dec(p + SL_NTRACKS); 97113813Sphk sl->sl_nsectors = be16dec(p + SL_NSECTORS); 98113818Sphk for (i = 0; i < SUN_NPART; i++) { 99113813Sphk sl->sl_part[i].sdkp_cyloffset = be32dec(p + SL_PART + 100113813Sphk (i * SDKP_SIZEOF) + SDKP_CYLOFFSET); 101113813Sphk sl->sl_part[i].sdkp_nsectors = be32dec(p + SL_PART + 102113813Sphk (i * SDKP_SIZEOF) + SDKP_NSECTORS); 103113813Sphk } 104113813Sphk sl->sl_magic = be16dec(p + SL_MAGIC); 105129963Sjoerg vtocsane = be32dec(p + SL_VTOC_SANITY); 106129963Sjoerg npart = be16dec(p + SL_VTOC_NPART); 107129963Sjoerg if (vtocsane == SUN_VTOC_SANE && npart == SUN_NPART) { 108129963Sjoerg /* 109129963Sjoerg * Seems we've got SVR4-compatible VTOC information 110129963Sjoerg * as well, decode it. 111129963Sjoerg */ 112129963Sjoerg sl->sl_vtoc_sane = vtocsane; 113129963Sjoerg sl->sl_vtoc_vers = be32dec(p + SL_VTOC_VERS); 114144328Sjoerg memcpy(sl->sl_vtoc_volname, p + SL_VTOC_VOLNAME, 115144328Sjoerg SUN_VOLNAME_LEN); 116129963Sjoerg sl->sl_vtoc_nparts = SUN_NPART; 117129963Sjoerg for (i = 0; i < SUN_NPART; i++) { 118129963Sjoerg sl->sl_vtoc_map[i].svtoc_tag = be16dec(p + 119129963Sjoerg SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_TAG); 120129963Sjoerg sl->sl_vtoc_map[i].svtoc_flag = be16dec(p + 121129963Sjoerg SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_FLAG); 122129963Sjoerg } 123129963Sjoerg } 124113818Sphk for (i = u = 0; i < SUN_SIZE; i += 2) 125113813Sphk u ^= be16dec(p + i); 126113813Sphk if (u == 0 && sl->sl_magic == SUN_DKMAGIC) 127113813Sphk return (0); 128113813Sphk else 129113813Sphk return (EINVAL); 130113813Sphk} 131113813Sphk 132113813Sphk/* 133113813Sphk * Encode the relevant fields into a sun disklabel, compute new checksum. 134113813Sphk */ 135113813Sphkvoid 136113813Sphksunlabel_enc(void *pp, struct sun_disklabel *sl) 137113813Sphk{ 138113813Sphk uint8_t *p; 139113813Sphk size_t i; 140113813Sphk u_int u; 141113813Sphk 142113813Sphk p = pp; 143113813Sphk for (i = 0; i < SL_TEXT_SIZEOF; i++) 144113813Sphk p[SL_TEXT + i] = sl->sl_text[i]; 145113813Sphk be16enc(p + SL_RPM, sl->sl_rpm); 146113813Sphk be16enc(p + SL_PCYLINDERS, sl->sl_pcylinders); 147113813Sphk be16enc(p + SL_SPARESPERCYL, sl->sl_sparespercyl); 148113813Sphk be16enc(p + SL_INTERLEAVE, sl->sl_interleave); 149113813Sphk be16enc(p + SL_NCYLINDERS, sl->sl_ncylinders); 150113813Sphk be16enc(p + SL_ACYLINDERS, sl->sl_acylinders); 151113813Sphk be16enc(p + SL_NTRACKS, sl->sl_ntracks); 152113813Sphk be16enc(p + SL_NSECTORS, sl->sl_nsectors); 153113818Sphk for (i = 0; i < SUN_NPART; i++) { 154113813Sphk be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_CYLOFFSET, 155113813Sphk sl->sl_part[i].sdkp_cyloffset); 156113813Sphk be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_NSECTORS, 157113813Sphk sl->sl_part[i].sdkp_nsectors); 158113813Sphk } 159113813Sphk be16enc(p + SL_MAGIC, sl->sl_magic); 160129963Sjoerg if (sl->sl_vtoc_sane == SUN_VTOC_SANE 161129963Sjoerg && sl->sl_vtoc_nparts == SUN_NPART) { 162129963Sjoerg /* 163129963Sjoerg * Write SVR4-compatible VTOC elements. 164129963Sjoerg */ 165129963Sjoerg be32enc(p + SL_VTOC_VERS, sl->sl_vtoc_vers); 166129963Sjoerg be32enc(p + SL_VTOC_SANITY, SUN_VTOC_SANE); 167144328Sjoerg memcpy(p + SL_VTOC_VOLNAME, sl->sl_vtoc_volname, 168144328Sjoerg SUN_VOLNAME_LEN); 169129963Sjoerg be16enc(p + SL_VTOC_NPART, SUN_NPART); 170129963Sjoerg for (i = 0; i < SUN_NPART; i++) { 171129963Sjoerg be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 172129963Sjoerg + SVTOC_TAG, 173129963Sjoerg sl->sl_vtoc_map[i].svtoc_tag); 174129963Sjoerg be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 175129963Sjoerg + SVTOC_FLAG, 176129963Sjoerg sl->sl_vtoc_map[i].svtoc_flag); 177129963Sjoerg } 178129963Sjoerg } 179113818Sphk for (i = u = 0; i < SUN_SIZE; i += 2) 180113813Sphk u ^= be16dec(p + i); 181113813Sphk be16enc(p + SL_CKSUM, u); 182113813Sphk} 183