geom_sunlabel_enc.c revision 129963
1113813Sphk/*- 2113813Sphk * Copyright (c) 2003 Jake Burkholder 3113813Sphk * Copyright (c) 2003 Poul-Henning Kamp 4129963Sjoerg * Copyright (c) 2004 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. 27113813Sphk * 28113813Sphk * 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 129963 2004-06-01 20:18:25Z joerg $"); 36116196Sobrien 37113813Sphk#include <sys/types.h> 38113813Sphk#include <sys/endian.h> 39113813Sphk#include <sys/errno.h> 40113813Sphk#include <sys/sun_disklabel.h> 41113813Sphk 42113813Sphk#define SL_TEXT 0x0 43113813Sphk#define SL_TEXT_SIZEOF 0x80 44129963Sjoerg#define SL_VTOC_VERS 0x80 45129963Sjoerg#define SL_VTOC_NPART 0x8c 46129963Sjoerg#define SL_VTOC_MAP 0x8e 47129963Sjoerg#define SL_VTOC_SANITY 0xbc 48113813Sphk#define SL_RPM 0x1a4 49113813Sphk#define SL_PCYLINDERS 0x1a6 50113813Sphk#define SL_SPARESPERCYL 0x1a8 51113813Sphk#define SL_INTERLEAVE 0x1ae 52113813Sphk#define SL_NCYLINDERS 0x1b0 53113813Sphk#define SL_ACYLINDERS 0x1b2 54113813Sphk#define SL_NTRACKS 0x1b4 55113813Sphk#define SL_NSECTORS 0x1b6 56113813Sphk#define SL_PART 0x1bc 57113813Sphk#define SL_MAGIC 0x1fc 58113813Sphk#define SL_CKSUM 0x1fe 59113813Sphk 60113813Sphk#define SDKP_CYLOFFSET 0 61113813Sphk#define SDKP_NSECTORS 0x4 62129963Sjoerg#define SDKP_SIZEOF 0x8 /* size of a partition entry */ 63113813Sphk 64129963Sjoerg#define SVTOC_TAG 0 65129963Sjoerg#define SVTOC_FLAG 0x2 66129963Sjoerg#define SVTOC_SIZEOF 0x4 /* size of a VTOC tag/flag entry */ 67129963Sjoerg 68113813Sphk/* 69113813Sphk * Decode the relevant fields of a sun disk label, and return zero if the 70113813Sphk * magic and checksum works out OK. 71113813Sphk */ 72113813Sphkint 73113813Sphksunlabel_dec(void const *pp, struct sun_disklabel *sl) 74113813Sphk{ 75113813Sphk const uint8_t *p; 76113813Sphk size_t i; 77113813Sphk u_int u; 78129963Sjoerg uint32_t vtocsane; 79129963Sjoerg uint16_t npart; 80113813Sphk 81113813Sphk p = pp; 82113813Sphk for (i = 0; i < sizeof(sl->sl_text); i++) 83113813Sphk sl->sl_text[i] = p[SL_TEXT + i]; 84113813Sphk sl->sl_rpm = be16dec(p + SL_RPM); 85113813Sphk sl->sl_pcylinders = be16dec(p + SL_PCYLINDERS); 86113813Sphk sl->sl_sparespercyl = be16dec(p + SL_SPARESPERCYL); 87113813Sphk sl->sl_interleave = be16dec(p + SL_INTERLEAVE); 88113813Sphk sl->sl_ncylinders = be16dec(p + SL_NCYLINDERS); 89113813Sphk sl->sl_acylinders = be16dec(p + SL_ACYLINDERS); 90113813Sphk sl->sl_ntracks = be16dec(p + SL_NTRACKS); 91113813Sphk sl->sl_nsectors = be16dec(p + SL_NSECTORS); 92113818Sphk for (i = 0; i < SUN_NPART; i++) { 93113813Sphk sl->sl_part[i].sdkp_cyloffset = be32dec(p + SL_PART + 94113813Sphk (i * SDKP_SIZEOF) + SDKP_CYLOFFSET); 95113813Sphk sl->sl_part[i].sdkp_nsectors = be32dec(p + SL_PART + 96113813Sphk (i * SDKP_SIZEOF) + SDKP_NSECTORS); 97113813Sphk } 98113813Sphk sl->sl_magic = be16dec(p + SL_MAGIC); 99129963Sjoerg vtocsane = be32dec(p + SL_VTOC_SANITY); 100129963Sjoerg npart = be16dec(p + SL_VTOC_NPART); 101129963Sjoerg if (vtocsane == SUN_VTOC_SANE && npart == SUN_NPART) { 102129963Sjoerg /* 103129963Sjoerg * Seems we've got SVR4-compatible VTOC information 104129963Sjoerg * as well, decode it. 105129963Sjoerg */ 106129963Sjoerg sl->sl_vtoc_sane = vtocsane; 107129963Sjoerg sl->sl_vtoc_vers = be32dec(p + SL_VTOC_VERS); 108129963Sjoerg sl->sl_vtoc_nparts = SUN_NPART; 109129963Sjoerg for (i = 0; i < SUN_NPART; i++) { 110129963Sjoerg sl->sl_vtoc_map[i].svtoc_tag = be16dec(p + 111129963Sjoerg SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_TAG); 112129963Sjoerg sl->sl_vtoc_map[i].svtoc_flag = be16dec(p + 113129963Sjoerg SL_VTOC_MAP + (i * SVTOC_SIZEOF) + SVTOC_FLAG); 114129963Sjoerg } 115129963Sjoerg } 116113818Sphk for (i = u = 0; i < SUN_SIZE; i += 2) 117113813Sphk u ^= be16dec(p + i); 118113813Sphk if (u == 0 && sl->sl_magic == SUN_DKMAGIC) 119113813Sphk return (0); 120113813Sphk else 121113813Sphk return (EINVAL); 122113813Sphk} 123113813Sphk 124113813Sphk/* 125113813Sphk * Encode the relevant fields into a sun disklabel, compute new checksum. 126113813Sphk */ 127113813Sphkvoid 128113813Sphksunlabel_enc(void *pp, struct sun_disklabel *sl) 129113813Sphk{ 130113813Sphk uint8_t *p; 131113813Sphk size_t i; 132113813Sphk u_int u; 133113813Sphk 134113813Sphk p = pp; 135113813Sphk for (i = 0; i < SL_TEXT_SIZEOF; i++) 136113813Sphk p[SL_TEXT + i] = sl->sl_text[i]; 137113813Sphk be16enc(p + SL_RPM, sl->sl_rpm); 138113813Sphk be16enc(p + SL_PCYLINDERS, sl->sl_pcylinders); 139113813Sphk be16enc(p + SL_SPARESPERCYL, sl->sl_sparespercyl); 140113813Sphk be16enc(p + SL_INTERLEAVE, sl->sl_interleave); 141113813Sphk be16enc(p + SL_NCYLINDERS, sl->sl_ncylinders); 142113813Sphk be16enc(p + SL_ACYLINDERS, sl->sl_acylinders); 143113813Sphk be16enc(p + SL_NTRACKS, sl->sl_ntracks); 144113813Sphk be16enc(p + SL_NSECTORS, sl->sl_nsectors); 145113818Sphk for (i = 0; i < SUN_NPART; i++) { 146113813Sphk be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_CYLOFFSET, 147113813Sphk sl->sl_part[i].sdkp_cyloffset); 148113813Sphk be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_NSECTORS, 149113813Sphk sl->sl_part[i].sdkp_nsectors); 150113813Sphk } 151113813Sphk be16enc(p + SL_MAGIC, sl->sl_magic); 152129963Sjoerg if (sl->sl_vtoc_sane == SUN_VTOC_SANE 153129963Sjoerg && sl->sl_vtoc_nparts == SUN_NPART) { 154129963Sjoerg /* 155129963Sjoerg * Write SVR4-compatible VTOC elements. 156129963Sjoerg */ 157129963Sjoerg be32enc(p + SL_VTOC_VERS, sl->sl_vtoc_vers); 158129963Sjoerg be32enc(p + SL_VTOC_SANITY, SUN_VTOC_SANE); 159129963Sjoerg be16enc(p + SL_VTOC_NPART, SUN_NPART); 160129963Sjoerg for (i = 0; i < SUN_NPART; i++) { 161129963Sjoerg be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 162129963Sjoerg + SVTOC_TAG, 163129963Sjoerg sl->sl_vtoc_map[i].svtoc_tag); 164129963Sjoerg be16enc(p + SL_VTOC_MAP + (i * SVTOC_SIZEOF) 165129963Sjoerg + SVTOC_FLAG, 166129963Sjoerg sl->sl_vtoc_map[i].svtoc_flag); 167129963Sjoerg } 168129963Sjoerg } 169113818Sphk for (i = u = 0; i < SUN_SIZE; i += 2) 170113813Sphk u ^= be16dec(p + i); 171113813Sphk be16enc(p + SL_CKSUM, u); 172113813Sphk} 173