Home | History | Annotate | Line # | Download | only in aml
      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 (at) 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