xref: /netbsd-src/usr.sbin/acpitools/aml/aml_store.c (revision 74b6b0adc8be769c28e13ff3e9c42e233d792cc8)
1 /*	$NetBSD: aml_store.c,v 1.5 2024/07/31 20:20:11 andvar Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 Takanori Watanabe
5  * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	Id: aml_store.c,v 1.22 2000/08/09 14:47:44 iwasaki Exp
30  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_store.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $
31  */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_store.c,v 1.5 2024/07/31 20:20:11 andvar Exp $");
34 
35 #include <sys/param.h>
36 
37 #include <acpi_common.h>
38 #include <aml/aml_amlmem.h>
39 #include <aml/aml_common.h>
40 #include <aml/aml_env.h>
41 #include <aml/aml_evalobj.h>
42 #include <aml/aml_name.h>
43 #include <aml/aml_obj.h>
44 #include <aml/aml_region.h>
45 #include <aml/aml_status.h>
46 #include <aml/aml_store.h>
47 
48 #ifndef _KERNEL
49 #include <assert.h>
50 #include <stdio.h>
51 #include <string.h>
52 
53 #include "debug.h"
54 #else /* _KERNEL */
55 #include <sys/systm.h>
56 #endif /* !_KERNEL */
57 
58 static void
59 aml_store_to_fieldname(struct aml_environ *env, union aml_object *obj,
60     struct aml_name *name)
61 {
62 	u_int8_t *buffer;
63 	struct	aml_name *wname, *oname, *iname;
64 	struct	aml_field *field;
65 	struct	aml_opregion *or;
66 	union	aml_object tobj, iobj, *tmpobj;
67 
68 	field = &name->property->field;
69 	oname = env->curname;
70 	iname = NULL;
71 	env->curname = name->parent;
72 	if (field->f.ftype == f_t_field) {
73 		wname = aml_search_name(env, field->f.fld.regname);
74 		if (wname == NULL ||
75 		    wname->property == NULL ||
76 		    wname->property->type != aml_t_opregion) {
77 			AML_DEBUGPRINT("Inappropriate Type\n");
78 			env->stat = aml_stat_panic;
79 			env->curname = oname;
80 			return;
81 		}
82 		or = &wname->property->opregion;
83 		switch (obj->type) {
84 		case aml_t_num:
85 			aml_region_write(env, or->space, field->flags,
86 			    obj->num.number, or->offset,
87 			    field->bitoffset, field->bitlen);
88 			AML_DEBUGPRINT("[write(%d, 0x%x, 0x%x)]",
89 			    or->space, obj->num.number,
90 			    or->offset + field->bitoffset / 8);
91 			break;
92 		case aml_t_buffer:
93 		case aml_t_bufferfield:
94 			if (obj->type == aml_t_buffer) {
95 				buffer = obj->buffer.data;
96 			} else {
97 				buffer = obj->bfld.origin;
98 				buffer += obj->bfld.bitoffset / 8;
99 			}
100 			aml_region_write_from_buffer(env, or->space,
101 			    field->flags, buffer, or->offset, field->bitoffset,
102 			    field->bitlen);
103 			break;
104 		case aml_t_regfield:
105 			if (or->space != obj->regfield.space) {
106 				AML_DEBUGPRINT("aml_store_to_fieldname: "
107 					       "Different type of space\n");
108 				break;
109 			}
110 			aml_region_bcopy(env, obj->regfield.space,
111 			    obj->regfield.flags, obj->regfield.offset,
112 			    obj->regfield.bitoffset, obj->regfield.bitlen,
113 			    field->flags, or->offset, field->bitoffset,
114 			    field->bitlen);
115 			break;
116 		default:
117 			AML_DEBUGPRINT("aml_store_to_fieldname: "
118 				       "Inappropriate Type of src object\n");
119 			break;
120 		}
121 	} else if (field->f.ftype == f_t_index) {
122 		iname = aml_search_name(env, field->f.ifld.indexname);
123 		wname = aml_search_name(env, field->f.ifld.dataname);
124 		iobj.type = aml_t_num;
125 		iobj.num.number = field->bitoffset / 8;	/* AccessType Boundary */
126 
127 		/* read whole values of IndexField */
128 		aml_store_to_name(env, &iobj, iname);
129 		tmpobj = aml_eval_name(env, wname);
130 
131 		/* make the values to be written */
132 		tobj.num = obj->num;
133  		tobj.num.number = aml_adjust_updatevalue(field->flags,
134  		    field->bitoffset & 7, field->bitlen,
135  		    tmpobj->num.number, obj->num.number);
136 
137 		/* write the values to IndexField */
138 		aml_store_to_name(env, &iobj, iname);
139 		aml_store_to_name(env, &tobj, wname);
140 	}
141 	env->curname = oname;
142 }
143 
144 static void
145 aml_store_to_buffer(struct aml_environ *env, union aml_object *obj,
146     union aml_object *buf, int offset)
147 {
148 	int	size;
149 	int	bitlen;
150 
151 	switch (obj->type) {
152 	case aml_t_num:
153 		if (offset > buf->buffer.size) {
154 			aml_realloc_object(buf, offset);
155 		}
156 		buf->buffer.data[offset] = obj->num.number & 0xff;
157 		AML_DEBUGPRINT("[Store number 0x%x to buffer]",
158 		    obj->num.number & 0xff);
159 		break;
160 	case aml_t_string:
161 		size = strlen((const char *)obj->str.string);
162 		if (buf->buffer.size - offset < size) {
163 			aml_realloc_object(buf, offset + size + 1);
164 		}
165 		strcpy((char *)&buf->buffer.data[offset],
166 		    (const char *)obj->str.string);
167 		AML_DEBUGPRINT("[Store string to buffer]");
168 		break;
169 	case aml_t_buffer:
170 		bzero(buf->buffer.data, buf->buffer.size);
171 		if (obj->buffer.size > buf->buffer.size) {
172 			size = buf->buffer.size;
173 		} else {
174 			size = obj->buffer.size;
175 		}
176 		bcopy(obj->buffer.data, buf->buffer.data, size);
177 		break;
178 	case aml_t_regfield:
179 		bitlen = (buf->buffer.size - offset) * 8;
180 		if (bitlen > obj->regfield.bitlen) {
181 			bitlen = obj->regfield.bitlen;
182 		}
183 		aml_region_read_into_buffer(env, obj->regfield.space,
184 		    obj->regfield.flags, obj->regfield.offset,
185 		    obj->regfield.bitoffset, bitlen,
186 		    buf->buffer.data + offset);
187 		break;
188 	default:
189 		goto not_yet;
190 	}
191 	return;
192 not_yet:
193 	AML_DEBUGPRINT("[XXX not supported yet]");
194 }
195 
196 
197 void
198 aml_store_to_object(struct aml_environ *env, union aml_object *src,
199     union aml_object * dest)
200 {
201 	u_int8_t *buffer, *srcbuf;
202 	int	offset, bitlen;
203 
204 	switch (dest->type) {
205 	case aml_t_num:
206 		if (src->type == aml_t_num) {
207 			dest->num = src->num;
208 			AML_DEBUGPRINT("[Store number 0x%x]", src->num.number);
209 		} else {
210 			env->stat = aml_stat_panic;
211 		}
212 		break;
213 	case aml_t_string:
214 	case aml_t_package:
215 		break;
216 	case aml_t_buffer:
217 		aml_store_to_buffer(env, src, dest, 0);
218 		break;
219 	case aml_t_bufferfield:
220 		buffer = dest->bfld.origin;
221 		offset = dest->bfld.bitoffset;
222 		bitlen = dest->bfld.bitlen;
223 
224 		switch (src->type) {
225 		case aml_t_num:
226 			if (aml_bufferfield_write(src->num.number, buffer, offset, bitlen)) {
227 				AML_DEBUGPRINT("aml_bufferfield_write() failed\n");
228 			}
229 			break;
230 		case aml_t_buffer:
231 		case aml_t_bufferfield:
232 			if (src->type == aml_t_buffer) {
233 				srcbuf = src->buffer.data;
234 			} else {
235 				srcbuf = src->bfld.origin;
236 				srcbuf += src->bfld.bitoffset / 8;
237 			}
238 			bcopy(srcbuf, buffer, bitlen / 8);
239 			break;
240 		case aml_t_regfield:
241 			aml_region_read_into_buffer(env, src->regfield.space,
242 			    src->regfield.flags, src->regfield.offset,
243 			    src->regfield.bitoffset, src->regfield.bitlen,
244 			    buffer);
245 			break;
246 		default:
247 			AML_DEBUGPRINT("not implemented yet");
248 			break;
249 		}
250 		break;
251 	case aml_t_debug:
252 		aml_showobject(src);
253 		break;
254 	default:
255 		AML_DEBUGPRINT("[Unimplemented %d]", dest->type);
256 		break;
257 	}
258 }
259 
260 static void
261 aml_store_to_objref(struct aml_environ *env, union aml_object *obj,
262     union aml_object *r)
263 {
264 	int	offset;
265 	union	aml_object *ref;
266 
267 	if (r->objref.ref == NULL) {
268 		r->objref.ref = aml_alloc_object(obj->type, NULL);	/* XXX */
269 		r->objref.nameref->property = r->objref.ref;
270 	}
271 	ref = r->objref.ref;
272 
273 	switch (ref->type) {
274 	case aml_t_buffer:
275 		offset = r->objref.offset;
276 		aml_store_to_buffer(env, obj, ref, r->objref.offset);
277 		break;
278 	case aml_t_package:
279 		offset = r->objref.offset;
280 		if (r->objref.ref->package.elements < offset) {
281 			aml_realloc_object(ref, offset);
282 		}
283 		if (ref->package.objects[offset] == NULL) {
284 			ref->package.objects[offset] = aml_copy_object(env, obj);
285 		} else {
286 			aml_store_to_object(env, obj, ref->package.objects[offset]);
287 		}
288 		break;
289 	default:
290 		aml_store_to_object(env, obj, ref);
291 		break;
292 	}
293 }
294 
295 /*
296  * Store to Named object
297  */
298 void
299 aml_store_to_name(struct aml_environ *env, union aml_object *obj,
300     struct aml_name *name)
301 {
302 	struct	aml_name *wname;
303 
304 	if (env->stat == aml_stat_panic) {
305 		return;
306 	}
307 	if (name == NULL || obj == NULL) {
308 		AML_DEBUGPRINT("[Try to store non-existent name]");
309 		return;
310 	}
311 	if (name->property == NULL) {
312 		name->property = aml_copy_object(env, obj);
313 		AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number);
314 		return;
315 	}
316 	if (name->property->type == aml_t_namestr) {
317 		wname = aml_search_name(env, name->property->nstr.dp);
318 		name = wname;
319 	}
320 	if (name == NULL) {
321 		env->stat = aml_stat_panic;
322 		return;
323 	}
324 	if (name->property == NULL || name->property->type == aml_t_null) {
325 		name->property = aml_copy_object(env, obj);
326 		AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number);
327 		return;
328 	}
329 	/* Writes to constant object are not allowed */
330 	if (name->property != NULL && name->property->type == aml_t_num &&
331 	    name->property->num.constant == 1) {
332 		return;
333 	}
334 	/* try to dereference */
335 	if (obj->type == aml_t_objref && obj->objref.deref == 0) {
336 		AML_DEBUGPRINT("Source object isn't dereferenced yet, "
337 			       "try to dereference anyway\n");
338 		obj->objref.deref = 1;
339 		obj = aml_eval_objref(env, obj);
340 	}
341 	switch (name->property->type) {
342 	case aml_t_field:
343 		aml_store_to_fieldname(env, obj, name);
344 		break;
345 	case aml_t_objref:
346 		aml_store_to_objref(env, obj, name->property);
347 		break;
348 	case aml_t_num:
349 		if (name == &env->tempname)
350 			break;
351 		/* FALLTHROUGH */
352 	default:
353 		aml_store_to_object(env, obj, name->property);
354 		break;
355 	}
356 }
357