1*d2e53371SPedro F. Giffuni /* $NetBSD: citrus_mapper_std.c,v 1.11 2018/06/11 18:03:38 kamil Exp $ */
2ad30f8e7SGabor Kovesdan
3ad30f8e7SGabor Kovesdan /*-
45e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause
55e53a4f9SPedro F. Giffuni *
6ad30f8e7SGabor Kovesdan * Copyright (c)2003, 2006 Citrus Project,
7ad30f8e7SGabor Kovesdan * All rights reserved.
8ad30f8e7SGabor Kovesdan *
9ad30f8e7SGabor Kovesdan * Redistribution and use in source and binary forms, with or without
10ad30f8e7SGabor Kovesdan * modification, are permitted provided that the following conditions
11ad30f8e7SGabor Kovesdan * are met:
12ad30f8e7SGabor Kovesdan * 1. Redistributions of source code must retain the above copyright
13ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer.
14ad30f8e7SGabor Kovesdan * 2. Redistributions in binary form must reproduce the above copyright
15ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer in the
16ad30f8e7SGabor Kovesdan * documentation and/or other materials provided with the distribution.
17ad30f8e7SGabor Kovesdan *
18ad30f8e7SGabor Kovesdan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ad30f8e7SGabor Kovesdan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ad30f8e7SGabor Kovesdan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ad30f8e7SGabor Kovesdan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ad30f8e7SGabor Kovesdan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ad30f8e7SGabor Kovesdan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ad30f8e7SGabor Kovesdan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ad30f8e7SGabor Kovesdan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ad30f8e7SGabor Kovesdan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ad30f8e7SGabor Kovesdan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ad30f8e7SGabor Kovesdan * SUCH DAMAGE.
29ad30f8e7SGabor Kovesdan */
30ad30f8e7SGabor Kovesdan
31ad30f8e7SGabor Kovesdan #include <sys/cdefs.h>
32ad30f8e7SGabor Kovesdan #include <sys/endian.h>
33ad30f8e7SGabor Kovesdan #include <sys/queue.h>
34ad30f8e7SGabor Kovesdan
35ad30f8e7SGabor Kovesdan #include <assert.h>
36ad30f8e7SGabor Kovesdan #include <errno.h>
37ad30f8e7SGabor Kovesdan #include <limits.h>
38ad30f8e7SGabor Kovesdan #include <stdint.h>
39ad30f8e7SGabor Kovesdan #include <stdio.h>
40ad30f8e7SGabor Kovesdan #include <stdlib.h>
41ad30f8e7SGabor Kovesdan #include <string.h>
42ad30f8e7SGabor Kovesdan
43ad30f8e7SGabor Kovesdan #include "citrus_namespace.h"
44ad30f8e7SGabor Kovesdan #include "citrus_types.h"
45ad30f8e7SGabor Kovesdan #include "citrus_bcs.h"
46ad30f8e7SGabor Kovesdan #include "citrus_region.h"
47ad30f8e7SGabor Kovesdan #include "citrus_mmap.h"
48ad30f8e7SGabor Kovesdan #include "citrus_module.h"
49ad30f8e7SGabor Kovesdan #include "citrus_hash.h"
50ad30f8e7SGabor Kovesdan #include "citrus_mapper.h"
51ad30f8e7SGabor Kovesdan #include "citrus_db.h"
52ad30f8e7SGabor Kovesdan #include "citrus_db_hash.h"
53ad30f8e7SGabor Kovesdan
54ad30f8e7SGabor Kovesdan #include "citrus_mapper_std.h"
55ad30f8e7SGabor Kovesdan #include "citrus_mapper_std_file.h"
56ad30f8e7SGabor Kovesdan
57ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
58ad30f8e7SGabor Kovesdan
59ad30f8e7SGabor Kovesdan _CITRUS_MAPPER_DECLS(mapper_std);
60ad30f8e7SGabor Kovesdan _CITRUS_MAPPER_DEF_OPS(mapper_std);
61ad30f8e7SGabor Kovesdan
62ad30f8e7SGabor Kovesdan
63ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
64ad30f8e7SGabor Kovesdan
65ad30f8e7SGabor Kovesdan int
_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops * ops)66ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops)
67ad30f8e7SGabor Kovesdan {
68ad30f8e7SGabor Kovesdan
69ad30f8e7SGabor Kovesdan memcpy(ops, &_citrus_mapper_std_mapper_ops,
70ad30f8e7SGabor Kovesdan sizeof(_citrus_mapper_std_mapper_ops));
71ad30f8e7SGabor Kovesdan
72ad30f8e7SGabor Kovesdan return (0);
73ad30f8e7SGabor Kovesdan }
74ad30f8e7SGabor Kovesdan
75ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
76ad30f8e7SGabor Kovesdan
77ad30f8e7SGabor Kovesdan static int
78ad30f8e7SGabor Kovesdan /*ARGSUSED*/
rowcol_convert(struct _citrus_mapper_std * __restrict ms,_index_t * __restrict dst,_index_t src,void * __restrict ps __unused)79ad30f8e7SGabor Kovesdan rowcol_convert(struct _citrus_mapper_std * __restrict ms,
80ad30f8e7SGabor Kovesdan _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
81ad30f8e7SGabor Kovesdan {
82ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_linear_zone *lz;
83ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_rowcol *rc;
84ad30f8e7SGabor Kovesdan _index_t idx = 0, n;
85ad30f8e7SGabor Kovesdan size_t i;
86ad30f8e7SGabor Kovesdan uint32_t conv;
87ad30f8e7SGabor Kovesdan
88ad30f8e7SGabor Kovesdan /* ps may be unused */
89ad30f8e7SGabor Kovesdan rc = &ms->ms_rowcol;
90ad30f8e7SGabor Kovesdan
91ad30f8e7SGabor Kovesdan for (i = rc->rc_src_rowcol_len * rc->rc_src_rowcol_bits,
92ad30f8e7SGabor Kovesdan lz = &rc->rc_src_rowcol[0]; i > 0; ++lz) {
93ad30f8e7SGabor Kovesdan i -= rc->rc_src_rowcol_bits;
94ad30f8e7SGabor Kovesdan n = (src >> i) & rc->rc_src_rowcol_mask;
95ad30f8e7SGabor Kovesdan if (n < lz->begin || n > lz->end) {
96ad30f8e7SGabor Kovesdan switch (rc->rc_oob_mode) {
97ad30f8e7SGabor Kovesdan case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
98ad30f8e7SGabor Kovesdan *dst = rc->rc_dst_invalid;
99ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_NONIDENTICAL);
100ad30f8e7SGabor Kovesdan case _CITRUS_MAPPER_STD_OOB_ILSEQ:
101ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_ILSEQ);
102ad30f8e7SGabor Kovesdan default:
103ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_FATAL);
104ad30f8e7SGabor Kovesdan }
105ad30f8e7SGabor Kovesdan }
106ad30f8e7SGabor Kovesdan idx = idx * lz->width + n - lz->begin;
107ad30f8e7SGabor Kovesdan }
108ad30f8e7SGabor Kovesdan switch (rc->rc_dst_unit_bits) {
109ad30f8e7SGabor Kovesdan case 8:
110ad30f8e7SGabor Kovesdan conv = _region_peek8(&rc->rc_table, idx);
111ad30f8e7SGabor Kovesdan break;
112ad30f8e7SGabor Kovesdan case 16:
113ad30f8e7SGabor Kovesdan conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
114ad30f8e7SGabor Kovesdan break;
115ad30f8e7SGabor Kovesdan case 32:
116ad30f8e7SGabor Kovesdan conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
117ad30f8e7SGabor Kovesdan break;
118ad30f8e7SGabor Kovesdan default:
119ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_FATAL);
120ad30f8e7SGabor Kovesdan }
121ad30f8e7SGabor Kovesdan
122ad30f8e7SGabor Kovesdan if (conv == rc->rc_dst_invalid) {
123ad30f8e7SGabor Kovesdan *dst = rc->rc_dst_invalid;
124ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_NONIDENTICAL);
125ad30f8e7SGabor Kovesdan }
126ad30f8e7SGabor Kovesdan if (conv == rc->rc_dst_ilseq)
127ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_ILSEQ);
128ad30f8e7SGabor Kovesdan
129ad30f8e7SGabor Kovesdan *dst = conv;
130ad30f8e7SGabor Kovesdan
131ad30f8e7SGabor Kovesdan return (_MAPPER_CONVERT_SUCCESS);
132ad30f8e7SGabor Kovesdan }
133ad30f8e7SGabor Kovesdan
134ad30f8e7SGabor Kovesdan static __inline int
set_linear_zone(struct _citrus_mapper_std_linear_zone * lz,uint32_t begin,uint32_t end)135ad30f8e7SGabor Kovesdan set_linear_zone(struct _citrus_mapper_std_linear_zone *lz,
136ad30f8e7SGabor Kovesdan uint32_t begin, uint32_t end)
137ad30f8e7SGabor Kovesdan {
138ad30f8e7SGabor Kovesdan
139ad30f8e7SGabor Kovesdan if (begin > end)
140ad30f8e7SGabor Kovesdan return (EFTYPE);
141ad30f8e7SGabor Kovesdan
142ad30f8e7SGabor Kovesdan lz->begin = begin;
143ad30f8e7SGabor Kovesdan lz->end = end;
144ad30f8e7SGabor Kovesdan lz->width= end - begin + 1;
145ad30f8e7SGabor Kovesdan
146ad30f8e7SGabor Kovesdan return (0);
147ad30f8e7SGabor Kovesdan }
148ad30f8e7SGabor Kovesdan
149ad30f8e7SGabor Kovesdan static __inline int
rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol * rc,struct _region * r)150ad30f8e7SGabor Kovesdan rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol *rc,
151ad30f8e7SGabor Kovesdan struct _region *r)
152ad30f8e7SGabor Kovesdan {
153ad30f8e7SGabor Kovesdan const struct _citrus_mapper_std_rowcol_info_compat_x *rcx;
154ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_linear_zone *lz;
155ad30f8e7SGabor Kovesdan uint32_t m, n;
156ad30f8e7SGabor Kovesdan int ret;
157ad30f8e7SGabor Kovesdan
158ad30f8e7SGabor Kovesdan rcx = _region_head(r);
159ad30f8e7SGabor Kovesdan
160ad30f8e7SGabor Kovesdan rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
161ad30f8e7SGabor Kovesdan rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
162ad30f8e7SGabor Kovesdan m = be32toh(rcx->rcx_src_col_bits);
163*d2e53371SPedro F. Giffuni n = 1U << (m - 1);
164ad30f8e7SGabor Kovesdan n |= n - 1;
165ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_bits = m;
166ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_mask = n;
167ad30f8e7SGabor Kovesdan
168ad30f8e7SGabor Kovesdan rc->rc_src_rowcol = malloc(2 *
169ad30f8e7SGabor Kovesdan sizeof(*rc->rc_src_rowcol));
170ad30f8e7SGabor Kovesdan if (rc->rc_src_rowcol == NULL)
171ad30f8e7SGabor Kovesdan return (ENOMEM);
172ad30f8e7SGabor Kovesdan lz = rc->rc_src_rowcol;
173ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_len = 1;
174ad30f8e7SGabor Kovesdan m = be32toh(rcx->rcx_src_row_begin);
175ad30f8e7SGabor Kovesdan n = be32toh(rcx->rcx_src_row_end);
176ad30f8e7SGabor Kovesdan if (m + n > 0) {
177ad30f8e7SGabor Kovesdan ret = set_linear_zone(lz, m, n);
1789ca40936STijl Coosemans if (ret != 0) {
1799ca40936STijl Coosemans free(rc->rc_src_rowcol);
1809ca40936STijl Coosemans rc->rc_src_rowcol = NULL;
181ad30f8e7SGabor Kovesdan return (ret);
1829ca40936STijl Coosemans }
183ad30f8e7SGabor Kovesdan ++rc->rc_src_rowcol_len, ++lz;
184ad30f8e7SGabor Kovesdan }
185ad30f8e7SGabor Kovesdan m = be32toh(rcx->rcx_src_col_begin);
186ad30f8e7SGabor Kovesdan n = be32toh(rcx->rcx_src_col_end);
187ad30f8e7SGabor Kovesdan
188ad30f8e7SGabor Kovesdan return (set_linear_zone(lz, m, n));
189ad30f8e7SGabor Kovesdan }
190ad30f8e7SGabor Kovesdan
191ad30f8e7SGabor Kovesdan static __inline int
rowcol_parse_variable(struct _citrus_mapper_std_rowcol * rc,struct _region * r)192ad30f8e7SGabor Kovesdan rowcol_parse_variable(struct _citrus_mapper_std_rowcol *rc,
193ad30f8e7SGabor Kovesdan struct _region *r)
194ad30f8e7SGabor Kovesdan {
195ad30f8e7SGabor Kovesdan const struct _citrus_mapper_std_rowcol_info_x *rcx;
196ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_linear_zone *lz;
197ad30f8e7SGabor Kovesdan size_t i;
198ad30f8e7SGabor Kovesdan uint32_t m, n;
199ad30f8e7SGabor Kovesdan int ret;
200ad30f8e7SGabor Kovesdan
201ad30f8e7SGabor Kovesdan rcx = _region_head(r);
202ad30f8e7SGabor Kovesdan
203ad30f8e7SGabor Kovesdan rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
204ad30f8e7SGabor Kovesdan rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
205ad30f8e7SGabor Kovesdan
206ad30f8e7SGabor Kovesdan m = be32toh(rcx->rcx_src_rowcol_bits);
207ad30f8e7SGabor Kovesdan n = 1 << (m - 1);
208ad30f8e7SGabor Kovesdan n |= n - 1;
209ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_bits = m;
210ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_mask = n;
211ad30f8e7SGabor Kovesdan
212ad30f8e7SGabor Kovesdan rc->rc_src_rowcol_len = be32toh(rcx->rcx_src_rowcol_len);
213ad30f8e7SGabor Kovesdan if (rc->rc_src_rowcol_len > _CITRUS_MAPPER_STD_ROWCOL_MAX)
214ad30f8e7SGabor Kovesdan return (EFTYPE);
215ad30f8e7SGabor Kovesdan rc->rc_src_rowcol = malloc(rc->rc_src_rowcol_len *
216ad30f8e7SGabor Kovesdan sizeof(*rc->rc_src_rowcol));
217ad30f8e7SGabor Kovesdan if (rc->rc_src_rowcol == NULL)
218ad30f8e7SGabor Kovesdan return (ENOMEM);
219ad30f8e7SGabor Kovesdan for (i = 0, lz = rc->rc_src_rowcol;
220ad30f8e7SGabor Kovesdan i < rc->rc_src_rowcol_len; ++i, ++lz) {
221ad30f8e7SGabor Kovesdan m = be32toh(rcx->rcx_src_rowcol[i].begin),
222ad30f8e7SGabor Kovesdan n = be32toh(rcx->rcx_src_rowcol[i].end);
223ad30f8e7SGabor Kovesdan ret = set_linear_zone(lz, m, n);
224ad30f8e7SGabor Kovesdan if (ret != 0) {
225ad30f8e7SGabor Kovesdan free(rc->rc_src_rowcol);
226ad30f8e7SGabor Kovesdan rc->rc_src_rowcol = NULL;
227ad30f8e7SGabor Kovesdan return (ret);
228ad30f8e7SGabor Kovesdan }
229ad30f8e7SGabor Kovesdan }
230ad30f8e7SGabor Kovesdan return (0);
231ad30f8e7SGabor Kovesdan }
232ad30f8e7SGabor Kovesdan
233ad30f8e7SGabor Kovesdan static void
rowcol_uninit(struct _citrus_mapper_std * ms)234ad30f8e7SGabor Kovesdan rowcol_uninit(struct _citrus_mapper_std *ms)
235ad30f8e7SGabor Kovesdan {
236ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_rowcol *rc;
237ad30f8e7SGabor Kovesdan
238ad30f8e7SGabor Kovesdan rc = &ms->ms_rowcol;
239ad30f8e7SGabor Kovesdan free(rc->rc_src_rowcol);
240ad30f8e7SGabor Kovesdan }
241ad30f8e7SGabor Kovesdan
242ad30f8e7SGabor Kovesdan static int
rowcol_init(struct _citrus_mapper_std * ms)243ad30f8e7SGabor Kovesdan rowcol_init(struct _citrus_mapper_std *ms)
244ad30f8e7SGabor Kovesdan {
245ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_linear_zone *lz;
246ad30f8e7SGabor Kovesdan struct _citrus_mapper_std_rowcol *rc;
247ad30f8e7SGabor Kovesdan const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
248ad30f8e7SGabor Kovesdan struct _region r;
249ad30f8e7SGabor Kovesdan uint64_t table_size;
250ad30f8e7SGabor Kovesdan size_t i;
251ad30f8e7SGabor Kovesdan int ret;
252ad30f8e7SGabor Kovesdan
253ad30f8e7SGabor Kovesdan ms->ms_convert = &rowcol_convert;
254ad30f8e7SGabor Kovesdan ms->ms_uninit = &rowcol_uninit;
255ad30f8e7SGabor Kovesdan rc = &ms->ms_rowcol;
256ad30f8e7SGabor Kovesdan
257ad30f8e7SGabor Kovesdan /* get table region */
258ad30f8e7SGabor Kovesdan ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
259ad30f8e7SGabor Kovesdan &rc->rc_table, NULL);
260ad30f8e7SGabor Kovesdan if (ret) {
261ad30f8e7SGabor Kovesdan if (ret == ENOENT)
262ad30f8e7SGabor Kovesdan ret = EFTYPE;
263ad30f8e7SGabor Kovesdan return (ret);
264ad30f8e7SGabor Kovesdan }
265ad30f8e7SGabor Kovesdan
266ad30f8e7SGabor Kovesdan /* get table information */
267ad30f8e7SGabor Kovesdan ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
268ad30f8e7SGabor Kovesdan if (ret) {
269ad30f8e7SGabor Kovesdan if (ret == ENOENT)
270ad30f8e7SGabor Kovesdan ret = EFTYPE;
271ad30f8e7SGabor Kovesdan return (ret);
272ad30f8e7SGabor Kovesdan }
273ad30f8e7SGabor Kovesdan switch (_region_size(&r)) {
274ad30f8e7SGabor Kovesdan case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE:
275ad30f8e7SGabor Kovesdan ret = rowcol_parse_variable_compat(rc, &r);
276ad30f8e7SGabor Kovesdan break;
277ad30f8e7SGabor Kovesdan case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE:
278ad30f8e7SGabor Kovesdan ret = rowcol_parse_variable(rc, &r);
279ad30f8e7SGabor Kovesdan break;
280ad30f8e7SGabor Kovesdan default:
281ad30f8e7SGabor Kovesdan return (EFTYPE);
282ad30f8e7SGabor Kovesdan }
283ad30f8e7SGabor Kovesdan if (ret != 0)
284ad30f8e7SGabor Kovesdan return (ret);
285ad30f8e7SGabor Kovesdan /* sanity check */
286ad30f8e7SGabor Kovesdan switch (rc->rc_src_rowcol_bits) {
287ad30f8e7SGabor Kovesdan case 8: case 16: case 32:
288ad30f8e7SGabor Kovesdan if (rc->rc_src_rowcol_len <= 32 / rc->rc_src_rowcol_bits)
289ad30f8e7SGabor Kovesdan break;
290ad30f8e7SGabor Kovesdan /*FALLTHROUGH*/
291ad30f8e7SGabor Kovesdan default:
292ad30f8e7SGabor Kovesdan return (EFTYPE);
293ad30f8e7SGabor Kovesdan }
294ad30f8e7SGabor Kovesdan
295ad30f8e7SGabor Kovesdan /* ilseq extension */
296ad30f8e7SGabor Kovesdan rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
297ad30f8e7SGabor Kovesdan rc->rc_dst_ilseq = rc->rc_dst_invalid;
298ad30f8e7SGabor Kovesdan ret = _db_lookup_by_s(ms->ms_db,
299ad30f8e7SGabor Kovesdan _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &r, NULL);
300ad30f8e7SGabor Kovesdan if (ret && ret != ENOENT)
301ad30f8e7SGabor Kovesdan return (ret);
302ad30f8e7SGabor Kovesdan if (_region_size(&r) < sizeof(*eix))
303ad30f8e7SGabor Kovesdan return (EFTYPE);
304ad30f8e7SGabor Kovesdan if (ret == 0) {
305ad30f8e7SGabor Kovesdan eix = _region_head(&r);
306ad30f8e7SGabor Kovesdan rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
307ad30f8e7SGabor Kovesdan rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
308ad30f8e7SGabor Kovesdan }
309ad30f8e7SGabor Kovesdan
310ad30f8e7SGabor Kovesdan /* calcurate expected table size */
311ad30f8e7SGabor Kovesdan i = rc->rc_src_rowcol_len;
312ad30f8e7SGabor Kovesdan lz = &rc->rc_src_rowcol[--i];
313ad30f8e7SGabor Kovesdan table_size = lz->width;
314ad30f8e7SGabor Kovesdan while (i > 0) {
315ad30f8e7SGabor Kovesdan lz = &rc->rc_src_rowcol[--i];
316ad30f8e7SGabor Kovesdan table_size *= lz->width;
317ad30f8e7SGabor Kovesdan }
318ad30f8e7SGabor Kovesdan table_size *= rc->rc_dst_unit_bits/8;
319ad30f8e7SGabor Kovesdan
320ad30f8e7SGabor Kovesdan if (table_size > UINT32_MAX ||
321ad30f8e7SGabor Kovesdan _region_size(&rc->rc_table) < table_size)
322ad30f8e7SGabor Kovesdan return (EFTYPE);
323ad30f8e7SGabor Kovesdan
324ad30f8e7SGabor Kovesdan return (0);
325ad30f8e7SGabor Kovesdan }
326ad30f8e7SGabor Kovesdan
327ad30f8e7SGabor Kovesdan typedef int (*initfunc_t)(struct _citrus_mapper_std *);
328ad30f8e7SGabor Kovesdan static const struct {
329ad30f8e7SGabor Kovesdan initfunc_t t_init;
330ad30f8e7SGabor Kovesdan const char *t_name;
331ad30f8e7SGabor Kovesdan } types[] = {
332ad30f8e7SGabor Kovesdan { &rowcol_init, _CITRUS_MAPPER_STD_TYPE_ROWCOL },
333ad30f8e7SGabor Kovesdan };
334ad30f8e7SGabor Kovesdan #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
335ad30f8e7SGabor Kovesdan
336ad30f8e7SGabor Kovesdan static int
337ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_init(struct _citrus_mapper_area * __restrict ma __unused,struct _citrus_mapper * __restrict cm,const char * __restrict curdir,const void * __restrict var,size_t lenvar,struct _citrus_mapper_traits * __restrict mt,size_t lenmt)338ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
339ad30f8e7SGabor Kovesdan struct _citrus_mapper * __restrict cm, const char * __restrict curdir,
340ad30f8e7SGabor Kovesdan const void * __restrict var, size_t lenvar,
341ad30f8e7SGabor Kovesdan struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
342ad30f8e7SGabor Kovesdan {
343ad30f8e7SGabor Kovesdan struct _citrus_mapper_std *ms;
344ad30f8e7SGabor Kovesdan char path[PATH_MAX];
345ad30f8e7SGabor Kovesdan const char *type;
346ad30f8e7SGabor Kovesdan int id, ret;
347ad30f8e7SGabor Kovesdan
348ad30f8e7SGabor Kovesdan /* set traits */
349ad30f8e7SGabor Kovesdan if (lenmt < sizeof(*mt)) {
350ad30f8e7SGabor Kovesdan ret = EINVAL;
351ad30f8e7SGabor Kovesdan goto err0;
352ad30f8e7SGabor Kovesdan }
353ad30f8e7SGabor Kovesdan mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
354ad30f8e7SGabor Kovesdan mt->mt_state_size = 0; /* stateless */
355ad30f8e7SGabor Kovesdan
356ad30f8e7SGabor Kovesdan /* alloc mapper std structure */
357ad30f8e7SGabor Kovesdan ms = malloc(sizeof(*ms));
358ad30f8e7SGabor Kovesdan if (ms == NULL) {
359ad30f8e7SGabor Kovesdan ret = errno;
360ad30f8e7SGabor Kovesdan goto err0;
361ad30f8e7SGabor Kovesdan }
362ad30f8e7SGabor Kovesdan
363ad30f8e7SGabor Kovesdan /* open mapper file */
364ad30f8e7SGabor Kovesdan snprintf(path, sizeof(path), "%s/%.*s", curdir, (int)lenvar,
365ad30f8e7SGabor Kovesdan (const char *)var);
366ad30f8e7SGabor Kovesdan ret = _map_file(&ms->ms_file, path);
367ad30f8e7SGabor Kovesdan if (ret)
368ad30f8e7SGabor Kovesdan goto err1;
369ad30f8e7SGabor Kovesdan
370ad30f8e7SGabor Kovesdan ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
371ad30f8e7SGabor Kovesdan &_db_hash_std, NULL);
372ad30f8e7SGabor Kovesdan if (ret)
373ad30f8e7SGabor Kovesdan goto err2;
374ad30f8e7SGabor Kovesdan
375ad30f8e7SGabor Kovesdan /* get mapper type */
376ad30f8e7SGabor Kovesdan ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
377ad30f8e7SGabor Kovesdan &type, NULL);
378ad30f8e7SGabor Kovesdan if (ret) {
379ad30f8e7SGabor Kovesdan if (ret == ENOENT)
380ad30f8e7SGabor Kovesdan ret = EFTYPE;
381ad30f8e7SGabor Kovesdan goto err3;
382ad30f8e7SGabor Kovesdan }
383ad30f8e7SGabor Kovesdan for (id = 0; id < NUM_OF_TYPES; id++)
384ad30f8e7SGabor Kovesdan if (_bcs_strcasecmp(type, types[id].t_name) == 0)
385ad30f8e7SGabor Kovesdan break;
386ad30f8e7SGabor Kovesdan
387ad30f8e7SGabor Kovesdan if (id == NUM_OF_TYPES)
388ad30f8e7SGabor Kovesdan goto err3;
389ad30f8e7SGabor Kovesdan
390ad30f8e7SGabor Kovesdan /* init the per-type structure */
391ad30f8e7SGabor Kovesdan ret = (*types[id].t_init)(ms);
392ad30f8e7SGabor Kovesdan if (ret)
393ad30f8e7SGabor Kovesdan goto err3;
394ad30f8e7SGabor Kovesdan
395ad30f8e7SGabor Kovesdan cm->cm_closure = ms;
396ad30f8e7SGabor Kovesdan
397ad30f8e7SGabor Kovesdan return (0);
398ad30f8e7SGabor Kovesdan
399ad30f8e7SGabor Kovesdan err3:
400ad30f8e7SGabor Kovesdan _db_close(ms->ms_db);
401ad30f8e7SGabor Kovesdan err2:
402ad30f8e7SGabor Kovesdan _unmap_file(&ms->ms_file);
403ad30f8e7SGabor Kovesdan err1:
404ad30f8e7SGabor Kovesdan free(ms);
405ad30f8e7SGabor Kovesdan err0:
406ad30f8e7SGabor Kovesdan return (ret);
407ad30f8e7SGabor Kovesdan }
408ad30f8e7SGabor Kovesdan
409ad30f8e7SGabor Kovesdan static void
410ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_uninit(struct _citrus_mapper * cm)411ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
412ad30f8e7SGabor Kovesdan {
413ad30f8e7SGabor Kovesdan struct _citrus_mapper_std *ms;
414ad30f8e7SGabor Kovesdan
415ad30f8e7SGabor Kovesdan ms = cm->cm_closure;
416ad30f8e7SGabor Kovesdan if (ms->ms_uninit)
417ad30f8e7SGabor Kovesdan (*ms->ms_uninit)(ms);
418ad30f8e7SGabor Kovesdan _db_close(ms->ms_db);
419ad30f8e7SGabor Kovesdan _unmap_file(&ms->ms_file);
420ad30f8e7SGabor Kovesdan free(ms);
421ad30f8e7SGabor Kovesdan }
422ad30f8e7SGabor Kovesdan
423ad30f8e7SGabor Kovesdan static void
424ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_init_state(void)425ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_init_state(void)
426ad30f8e7SGabor Kovesdan {
427ad30f8e7SGabor Kovesdan
428ad30f8e7SGabor Kovesdan }
429ad30f8e7SGabor Kovesdan
430ad30f8e7SGabor Kovesdan static int
431ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,_index_t * __restrict dst,_index_t src,void * __restrict ps)432ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
433ad30f8e7SGabor Kovesdan _index_t * __restrict dst, _index_t src, void * __restrict ps)
434ad30f8e7SGabor Kovesdan {
435ad30f8e7SGabor Kovesdan struct _citrus_mapper_std *ms;
436ad30f8e7SGabor Kovesdan
437ad30f8e7SGabor Kovesdan ms = cm->cm_closure;
438ad30f8e7SGabor Kovesdan return ((*ms->ms_convert)(ms, dst, src, ps));
439ad30f8e7SGabor Kovesdan }
440