geom_sunlabel_enc.c revision 113818
1177633Sdfr/*-
2177633Sdfr * Copyright (c) 2003 Jake Burkholder
3177633Sdfr * Copyright (c) 2003 Poul-Henning Kamp
4177633Sdfr * All rights reserved.
5177633Sdfr *
6177633Sdfr * Redistribution and use in source and binary forms, with or without
7177633Sdfr * modification, are permitted provided that the following conditions
8177633Sdfr * are met:
9177633Sdfr * 1. Redistributions of source code must retain the above copyright
10177633Sdfr *    notice, this list of conditions and the following disclaimer.
11177633Sdfr * 2. Redistributions in binary form must reproduce the above copyright
12177633Sdfr *    notice, this list of conditions and the following disclaimer in the
13177633Sdfr *    documentation and/or other materials provided with the distribution.
14177633Sdfr *
15177633Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16177633Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17177633Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18177633Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19177633Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20177633Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21177633Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22177633Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23177633Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24177633Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25177633Sdfr * SUCH DAMAGE.
26177633Sdfr *
27177633Sdfr * $FreeBSD: head/sys/geom/geom_sunlabel_enc.c 113818 2003-04-21 19:42:36Z phk $
28177633Sdfr *
29177633Sdfr * Functions to encode or decode struct sun_disklabel into a bytestream
30177633Sdfr * of correct endianess and packing.
31177633Sdfr *
32177633Sdfr * NB!  This file must be usable both in kernel and userland.
33177633Sdfr *
34177633Sdfr */
35177633Sdfr
36177633Sdfr#include <sys/types.h>
37177633Sdfr#include <sys/endian.h>
38177633Sdfr#include <sys/errno.h>
39177633Sdfr#include <sys/sun_disklabel.h>
40177633Sdfr
41177633Sdfr#define	SL_TEXT		0x0
42177633Sdfr#define	SL_TEXT_SIZEOF	0x80
43177633Sdfr#define	SL_RPM		0x1a4
44177633Sdfr#define	SL_PCYLINDERS	0x1a6
45177633Sdfr#define	SL_SPARESPERCYL	0x1a8
46177633Sdfr#define	SL_INTERLEAVE	0x1ae
47177633Sdfr#define	SL_NCYLINDERS	0x1b0
48177633Sdfr#define	SL_ACYLINDERS	0x1b2
49177633Sdfr#define	SL_NTRACKS	0x1b4
50177633Sdfr#define	SL_NSECTORS	0x1b6
51177633Sdfr#define	SL_PART		0x1bc
52184588Sdfr#define	SL_MAGIC	0x1fc
53177633Sdfr#define	SL_CKSUM	0x1fe
54184588Sdfr
55177633Sdfr#define	SDKP_CYLOFFSET	0
56184588Sdfr#define	SDKP_NSECTORS	0x4
57177633Sdfr#define	SDKP_SIZEOF	0x8
58184588Sdfr
59177633Sdfr/*
60177633Sdfr * Decode the relevant fields of a sun disk label, and return zero if the
61177633Sdfr * magic and checksum works out OK.
62177633Sdfr */
63177633Sdfrint
64184588Sdfrsunlabel_dec(void const *pp, struct sun_disklabel *sl)
65177633Sdfr{
66177685Sdfr	const uint8_t *p;
67177633Sdfr	size_t i;
68177633Sdfr	u_int u;
69184588Sdfr
70177633Sdfr	p = pp;
71177633Sdfr	for (i = 0; i < sizeof(sl->sl_text); i++)
72177633Sdfr		sl->sl_text[i] = p[SL_TEXT + i];
73184588Sdfr	sl->sl_rpm = be16dec(p + SL_RPM);
74184588Sdfr	sl->sl_pcylinders = be16dec(p + SL_PCYLINDERS);
75177633Sdfr	sl->sl_sparespercyl = be16dec(p + SL_SPARESPERCYL);
76177633Sdfr	sl->sl_interleave = be16dec(p + SL_INTERLEAVE);
77177633Sdfr	sl->sl_ncylinders = be16dec(p + SL_NCYLINDERS);
78184588Sdfr	sl->sl_acylinders = be16dec(p + SL_ACYLINDERS);
79184588Sdfr	sl->sl_ntracks = be16dec(p + SL_NTRACKS);
80184588Sdfr	sl->sl_nsectors = be16dec(p + SL_NSECTORS);
81177633Sdfr	for (i = 0; i < SUN_NPART; i++) {
82184588Sdfr		sl->sl_part[i].sdkp_cyloffset = be32dec(p + SL_PART +
83177633Sdfr		    (i * SDKP_SIZEOF) + SDKP_CYLOFFSET);
84177633Sdfr		sl->sl_part[i].sdkp_nsectors = be32dec(p + SL_PART +
85177633Sdfr		    (i * SDKP_SIZEOF) + SDKP_NSECTORS);
86177633Sdfr	}
87177633Sdfr	sl->sl_magic = be16dec(p + SL_MAGIC);
88177633Sdfr	for (i = u = 0; i < SUN_SIZE; i += 2)
89184588Sdfr		u ^= be16dec(p + i);
90184588Sdfr	if (u == 0 && sl->sl_magic == SUN_DKMAGIC)
91184588Sdfr		return (0);
92177633Sdfr	else
93177633Sdfr		return (EINVAL);
94177633Sdfr}
95184588Sdfr
96184588Sdfr/*
97184588Sdfr * Encode the relevant fields into a sun disklabel, compute new checksum.
98184588Sdfr */
99184588Sdfrvoid
100177633Sdfrsunlabel_enc(void *pp, struct sun_disklabel *sl)
101184588Sdfr{
102184588Sdfr	uint8_t *p;
103184588Sdfr	size_t i;
104184588Sdfr	u_int u;
105184588Sdfr
106184588Sdfr	p = pp;
107184588Sdfr	for (i = 0; i < SL_TEXT_SIZEOF; i++)
108184588Sdfr		p[SL_TEXT + i] = sl->sl_text[i];
109184588Sdfr	be16enc(p + SL_RPM, sl->sl_rpm);
110184588Sdfr	be16enc(p + SL_PCYLINDERS, sl->sl_pcylinders);
111184588Sdfr	be16enc(p + SL_SPARESPERCYL, sl->sl_sparespercyl);
112184588Sdfr	be16enc(p + SL_INTERLEAVE, sl->sl_interleave);
113184588Sdfr	be16enc(p + SL_NCYLINDERS, sl->sl_ncylinders);
114184588Sdfr	be16enc(p + SL_ACYLINDERS, sl->sl_acylinders);
115184588Sdfr	be16enc(p + SL_NTRACKS, sl->sl_ntracks);
116184588Sdfr	be16enc(p + SL_NSECTORS, sl->sl_nsectors);
117184588Sdfr	for (i = 0; i < SUN_NPART; i++) {
118184588Sdfr		be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_CYLOFFSET,
119184588Sdfr		    sl->sl_part[i].sdkp_cyloffset);
120184588Sdfr		be32enc(p + SL_PART + (i * SDKP_SIZEOF) + SDKP_NSECTORS,
121184588Sdfr		    sl->sl_part[i].sdkp_nsectors);
122184588Sdfr	}
123184588Sdfr	be16enc(p + SL_MAGIC, sl->sl_magic);
124184588Sdfr	for (i = u = 0; i < SUN_SIZE; i += 2)
125184588Sdfr		u ^= be16dec(p + i);
126184588Sdfr	be16enc(p + SL_CKSUM, u);
127184588Sdfr}
128184588Sdfr