1/* $NetBSD: aml_store.c,v 1.3 2021/09/03 22:33:18 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.3 2021/09/03 22:33:18 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 58static void 59aml_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("Inappropreate 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 "Inappropreate 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 144static void 145aml_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; 192not_yet: 193 AML_DEBUGPRINT("[XXX not supported yet]"); 194} 195 196 197void 198aml_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 260static void 261aml_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 */ 298void 299aml_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