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