aml_name.c revision 1.1 1 1.1 christos /* $NetBSD: aml_name.c,v 1.1 2007/01/14 04:36:13 christos 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 Yasuo Yokoyama
6 1.1 christos * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki (at) FreeBSD.org>
7 1.1 christos * All rights reserved.
8 1.1 christos *
9 1.1 christos * Redistribution and use in source and binary forms, with or without
10 1.1 christos * modification, are permitted provided that the following conditions
11 1.1 christos * are met:
12 1.1 christos * 1. Redistributions of source code must retain the above copyright
13 1.1 christos * notice, this list of conditions and the following disclaimer.
14 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 christos * notice, this list of conditions and the following disclaimer in the
16 1.1 christos * documentation and/or other materials provided with the distribution.
17 1.1 christos *
18 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.1 christos * SUCH DAMAGE.
29 1.1 christos *
30 1.1 christos * Id: aml_name.c,v 1.15 2000/08/16 18:14:53 iwasaki Exp
31 1.1 christos * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_name.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $
32 1.1 christos */
33 1.1 christos #include <sys/cdefs.h>
34 1.1 christos __RCSID("$NetBSD: aml_name.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
35 1.1 christos
36 1.1 christos #include <sys/param.h>
37 1.1 christos
38 1.1 christos #include <acpi_common.h>
39 1.1 christos #include <aml/aml_amlmem.h>
40 1.1 christos #include <aml/aml_common.h>
41 1.1 christos #include <aml/aml_env.h>
42 1.1 christos #include <aml/aml_name.h>
43 1.1 christos
44 1.1 christos #ifndef _KERNEL
45 1.1 christos #include <stdio.h>
46 1.1 christos #include <stdlib.h>
47 1.1 christos #include <string.h>
48 1.1 christos
49 1.1 christos #include "debug.h"
50 1.1 christos #else /* _KERNEL */
51 1.1 christos #include <sys/systm.h>
52 1.1 christos #endif /* !_KERNEL */
53 1.1 christos
54 1.1 christos static struct aml_name *aml_find_name(struct aml_name *, const u_int8_t *);
55 1.1 christos static struct aml_name *aml_new_name(struct aml_name *, const u_int8_t *);
56 1.1 christos static void aml_delete_name(struct aml_name *);
57 1.1 christos
58 1.1 christos static struct aml_name rootname = {"\\", NULL, NULL, NULL, NULL, NULL};
59 1.1 christos
60 1.1 christos static struct aml_name_group root_group = {
61 1.1 christos AML_NAME_GROUP_ROOT,
62 1.1 christos &rootname,
63 1.1 christos NULL
64 1.1 christos };
65 1.1 christos
66 1.1 christos struct aml_name_group *name_group_list = &root_group;
67 1.1 christos struct aml_local_stack *stack_top = NULL;
68 1.1 christos
69 1.1 christos struct aml_name *
70 1.1 christos aml_get_rootname()
71 1.1 christos {
72 1.1 christos
73 1.1 christos return (&rootname);
74 1.1 christos }
75 1.1 christos
76 1.1 christos static struct aml_name *
77 1.1 christos aml_find_name(struct aml_name *parent, const u_int8_t *name)
78 1.1 christos {
79 1.1 christos struct aml_name *result;
80 1.1 christos
81 1.1 christos if (!parent)
82 1.1 christos parent = &rootname;
83 1.1 christos for (result = parent->child; result; result = result->brother)
84 1.1 christos if (!strncmp(result->name, (const char *)name, 4))
85 1.1 christos break;
86 1.1 christos return (result);
87 1.1 christos }
88 1.1 christos
89 1.1 christos /*
90 1.1 christos * Parse given namesppace expression and find a first matched object
91 1.1 christos * under given level of the tree by depth first search.
92 1.1 christos */
93 1.1 christos
94 1.1 christos struct aml_name *
95 1.1 christos aml_find_from_namespace(struct aml_name *parent, const char *name)
96 1.1 christos {
97 1.1 christos const char *ptr;
98 1.1 christos int len;
99 1.1 christos struct aml_name *result;
100 1.1 christos
101 1.1 christos ptr = name;
102 1.1 christos if (!parent)
103 1.1 christos parent = &rootname;
104 1.1 christos
105 1.1 christos if (ptr[0] == '\\') {
106 1.1 christos ptr++;
107 1.1 christos parent = &rootname;
108 1.1 christos }
109 1.1 christos for (len = 0; ptr[len] != '.' && ptr[len] != '\0'; len++)
110 1.1 christos ;
111 1.1 christos
112 1.1 christos for (result = parent->child; result; result = result->brother) {
113 1.1 christos if (!strncmp(result->name, ptr, len)) {
114 1.1 christos if (ptr[len] == '\0' || ptr[len + 1] == '\0') {
115 1.1 christos return (result);
116 1.1 christos }
117 1.1 christos ptr += len;
118 1.1 christos if (ptr[0] != '.') {
119 1.1 christos return (NULL);
120 1.1 christos }
121 1.1 christos ptr++;
122 1.1 christos return (aml_find_from_namespace(result, ptr));
123 1.1 christos }
124 1.1 christos }
125 1.1 christos
126 1.1 christos return (NULL);
127 1.1 christos }
128 1.1 christos
129 1.1 christos static void
130 1.1 christos _aml_apply_foreach_found_objects(struct aml_name *parent, char *name,
131 1.1 christos int len, int shallow, int (*func)(struct aml_name *, va_list), va_list ap)
132 1.1 christos {
133 1.1 christos struct aml_name *child, *ptr;
134 1.1 christos
135 1.1 christos child = ptr = NULL;
136 1.1 christos
137 1.1 christos /* function to apply must be specified */
138 1.1 christos if (func == NULL) {
139 1.1 christos return;
140 1.1 christos }
141 1.1 christos
142 1.1 christos for (child = parent->child; child; child = child->brother) {
143 1.1 christos if (!strncmp(child->name, name, len)) {
144 1.1 christos /* if function call was failed, stop searching */
145 1.1 christos if (func(child, ap) != 0) {
146 1.1 christos return;
147 1.1 christos }
148 1.1 christos }
149 1.1 christos }
150 1.1 christos
151 1.1 christos if (shallow == 1) {
152 1.1 christos return;
153 1.1 christos }
154 1.1 christos
155 1.1 christos for (ptr = parent->child; ptr; ptr = ptr->brother) {
156 1.1 christos /* do more searching */
157 1.1 christos _aml_apply_foreach_found_objects(ptr, name, len, 0, func, ap);
158 1.1 christos }
159 1.1 christos }
160 1.1 christos
161 1.1 christos /*
162 1.1 christos * Find named objects as many as possible under given level of
163 1.1 christos * namespace, and apply given callback function for each
164 1.1 christos * named objects found. If the callback function returns non-zero
165 1.1 christos * value, then the search terminates immediately.
166 1.1 christos * Note that object name expression is used as forward substring match,
167 1.1 christos * not exact match. The name expression "_L" will match for objects
168 1.1 christos * which have name starting with "_L" such as "\_SB_.LID_._LID" and
169 1.1 christos * "\_GPE._L00" and so on. The name expression can include parent object
170 1.1 christos * name in it like "\_GPE._L". In this case, GPE X level wake handlers
171 1.1 christos * will be found under "\_GPE" in shallow level.
172 1.1 christos */
173 1.1 christos
174 1.1 christos void
175 1.1 christos aml_apply_foreach_found_objects(struct aml_name *start, char *name,
176 1.1 christos int (*func)(struct aml_name *, va_list), ...)
177 1.1 christos {
178 1.1 christos int i, len, has_dot, last_is_dot, shallow;
179 1.1 christos struct aml_name *child, *parent;
180 1.1 christos va_list ap;
181 1.1 christos
182 1.1 christos shallow = 0;
183 1.1 christos if (start == NULL) {
184 1.1 christos parent = &rootname;
185 1.1 christos } else {
186 1.1 christos parent = start;
187 1.1 christos }
188 1.1 christos if (name[0] == '\\') {
189 1.1 christos name++;
190 1.1 christos parent = &rootname;
191 1.1 christos shallow = 1;
192 1.1 christos }
193 1.1 christos
194 1.1 christos len = strlen(name);
195 1.1 christos last_is_dot = 0;
196 1.1 christos /* the last dot should be ignored */
197 1.1 christos if (len > 0 && name[len - 1] == '.') {
198 1.1 christos len--;
199 1.1 christos last_is_dot = 1;
200 1.1 christos }
201 1.1 christos
202 1.1 christos has_dot = 0;
203 1.1 christos for (i = 0; i < len - 1; i++) {
204 1.1 christos if (name[i] == '.') {
205 1.1 christos has_dot = 1;
206 1.1 christos break;
207 1.1 christos }
208 1.1 christos }
209 1.1 christos
210 1.1 christos /* try to parse expression and find any matched object. */
211 1.1 christos if (has_dot == 1) {
212 1.1 christos child = aml_find_from_namespace(parent, name);
213 1.1 christos if (child == NULL) {
214 1.1 christos return;
215 1.1 christos }
216 1.1 christos
217 1.1 christos /*
218 1.1 christos * we have at least one object matched, search all objects
219 1.1 christos * under upper level of the found object.
220 1.1 christos */
221 1.1 christos parent = child->parent;
222 1.1 christos
223 1.1 christos /* find the last `.' */
224 1.1 christos for (name = name + len - 1; *name != '.'; name--)
225 1.1 christos ;
226 1.1 christos name++;
227 1.1 christos len = strlen(name) - last_is_dot;
228 1.1 christos shallow = 1;
229 1.1 christos }
230 1.1 christos
231 1.1 christos if (len > 4) {
232 1.1 christos return;
233 1.1 christos }
234 1.1 christos
235 1.1 christos va_start(ap, func);
236 1.1 christos _aml_apply_foreach_found_objects(parent, name, len, shallow, func, ap);
237 1.1 christos va_end(ap);
238 1.1 christos }
239 1.1 christos
240 1.1 christos struct aml_name_group *
241 1.1 christos aml_new_name_group(int id)
242 1.1 christos {
243 1.1 christos struct aml_name_group *result;
244 1.1 christos
245 1.1 christos result = memman_alloc(aml_memman, memid_aml_name_group);
246 1.1 christos result->id = id;
247 1.1 christos result->head = NULL;
248 1.1 christos result->next = name_group_list;
249 1.1 christos name_group_list = result;
250 1.1 christos return (result);
251 1.1 christos }
252 1.1 christos
253 1.1 christos void
254 1.1 christos aml_delete_name_group(struct aml_name_group *target)
255 1.1 christos {
256 1.1 christos struct aml_name_group *previous;
257 1.1 christos
258 1.1 christos previous = name_group_list;
259 1.1 christos if (previous == target)
260 1.1 christos name_group_list = target->next;
261 1.1 christos else {
262 1.1 christos while (previous && previous->next != target)
263 1.1 christos previous = previous->next;
264 1.1 christos if (previous)
265 1.1 christos previous->next = target->next;
266 1.1 christos }
267 1.1 christos target->next = NULL;
268 1.1 christos if (target->head)
269 1.1 christos aml_delete_name(target->head);
270 1.1 christos memman_free(aml_memman, memid_aml_name_group, target);
271 1.1 christos }
272 1.1 christos
273 1.1 christos static struct aml_name *
274 1.1 christos aml_new_name(struct aml_name *parent, const u_int8_t *name)
275 1.1 christos {
276 1.1 christos struct aml_name *newname;
277 1.1 christos
278 1.1 christos if ((newname = aml_find_name(parent, name)) != NULL)
279 1.1 christos return (newname);
280 1.1 christos
281 1.1 christos newname = memman_alloc(aml_memman, memid_aml_name);
282 1.1 christos strncpy(newname->name, (const char *)name, 4);
283 1.1 christos newname->parent = parent;
284 1.1 christos newname->child = NULL;
285 1.1 christos newname->property = NULL;
286 1.1 christos if (parent->child)
287 1.1 christos newname->brother = parent->child;
288 1.1 christos else
289 1.1 christos newname->brother = NULL;
290 1.1 christos parent->child = newname;
291 1.1 christos
292 1.1 christos newname->chain = name_group_list->head;
293 1.1 christos name_group_list->head = newname;
294 1.1 christos
295 1.1 christos return (newname);
296 1.1 christos }
297 1.1 christos
298 1.1 christos /*
299 1.1 christos * NOTE:
300 1.1 christos * aml_delete_name() doesn't maintain aml_name_group::{head,tail}.
301 1.1 christos */
302 1.1 christos static void
303 1.1 christos aml_delete_name(struct aml_name *target)
304 1.1 christos {
305 1.1 christos struct aml_name *next;
306 1.1 christos struct aml_name *ptr;
307 1.1 christos
308 1.1 christos for (; target; target = next) {
309 1.1 christos next = target->chain;
310 1.1 christos if (target->child) {
311 1.1 christos target->chain = NULL;
312 1.1 christos continue;
313 1.1 christos }
314 1.1 christos if (target->brother) {
315 1.1 christos if (target->parent) {
316 1.1 christos if (target->parent->child == target) {
317 1.1 christos target->parent->child = target->brother;
318 1.1 christos } else {
319 1.1 christos ptr = target->parent->child;
320 1.1 christos while (ptr && ptr->brother != target)
321 1.1 christos ptr = ptr->brother;
322 1.1 christos if (ptr)
323 1.1 christos ptr->brother = target->brother;
324 1.1 christos }
325 1.1 christos target->brother = NULL;
326 1.1 christos }
327 1.1 christos } else if (target->parent) {
328 1.1 christos target->parent->child = NULL;
329 1.1 christos }
330 1.1 christos aml_free_object(&target->property);
331 1.1 christos memman_free(aml_memman, memid_aml_name, target);
332 1.1 christos }
333 1.1 christos }
334 1.1 christos
335 1.1 christos #define AML_SEARCH_NAME 0
336 1.1 christos #define AML_CREATE_NAME 1
337 1.1 christos static struct aml_name *aml_nameman(struct aml_environ *, const u_int8_t *, int);
338 1.1 christos
339 1.1 christos struct aml_name *
340 1.1 christos aml_search_name(struct aml_environ *env, const u_int8_t *dp)
341 1.1 christos {
342 1.1 christos
343 1.1 christos return (aml_nameman(env, dp, AML_SEARCH_NAME));
344 1.1 christos }
345 1.1 christos
346 1.1 christos struct aml_name *
347 1.1 christos aml_create_name(struct aml_environ *env, const u_int8_t *dp)
348 1.1 christos {
349 1.1 christos
350 1.1 christos return (aml_nameman(env, dp, AML_CREATE_NAME));
351 1.1 christos }
352 1.1 christos
353 1.1 christos static struct aml_name *
354 1.1 christos aml_nameman(struct aml_environ *env, const u_int8_t *dp, int flag)
355 1.1 christos {
356 1.1 christos int segcount;
357 1.1 christos int i;
358 1.1 christos struct aml_name *newname, *curname;
359 1.1 christos struct aml_name *(*searchfunc) (struct aml_name *, const u_int8_t *);
360 1.1 christos
361 1.1 christos #define CREATECHECK() do { \
362 1.1 christos if (newname == NULL) { \
363 1.1 christos AML_DEBUGPRINT("ERROR CANNOT FIND NAME\n"); \
364 1.1 christos env->stat = aml_stat_panic; \
365 1.1 christos return (NULL); \
366 1.1 christos } \
367 1.1 christos } while(0)
368 1.1 christos
369 1.1 christos searchfunc = (flag == AML_CREATE_NAME) ? aml_new_name : aml_find_name;
370 1.1 christos newname = env->curname;
371 1.1 christos if (dp[0] == '\\') {
372 1.1 christos newname = &rootname;
373 1.1 christos dp++;
374 1.1 christos } else if (dp[0] == '^') {
375 1.1 christos while (dp[0] == '^') {
376 1.1 christos newname = newname->parent;
377 1.1 christos CREATECHECK();
378 1.1 christos dp++;
379 1.1 christos }
380 1.1 christos }
381 1.1 christos if (dp[0] == 0x00) { /* NullName */
382 1.1 christos dp++;
383 1.1 christos } else if (dp[0] == 0x2e) { /* DualNamePrefix */
384 1.1 christos newname = (*searchfunc) (newname, dp + 1);
385 1.1 christos CREATECHECK();
386 1.1 christos newname = (*searchfunc) (newname, dp + 5);
387 1.1 christos CREATECHECK();
388 1.1 christos } else if (dp[0] == 0x2f) { /* MultiNamePrefix */
389 1.1 christos segcount = dp[1];
390 1.1 christos for (i = 0, dp += 2; i < segcount; i++, dp += 4) {
391 1.1 christos newname = (*searchfunc) (newname, dp);
392 1.1 christos CREATECHECK();
393 1.1 christos }
394 1.1 christos } else if (flag == AML_CREATE_NAME) { /* NameSeg */
395 1.1 christos newname = aml_new_name(newname, dp);
396 1.1 christos CREATECHECK();
397 1.1 christos } else {
398 1.1 christos curname = newname;
399 1.1 christos for (;;) {
400 1.1 christos newname = aml_find_name(curname, dp);
401 1.1 christos if (newname != NULL)
402 1.1 christos break;
403 1.1 christos if (curname == &rootname)
404 1.1 christos break;
405 1.1 christos curname = curname->parent;
406 1.1 christos }
407 1.1 christos }
408 1.1 christos return (newname);
409 1.1 christos }
410 1.1 christos
411 1.1 christos #undef CREATECHECK
412 1.1 christos
413 1.1 christos struct aml_local_stack *
414 1.1 christos aml_local_stack_create()
415 1.1 christos {
416 1.1 christos struct aml_local_stack *result;
417 1.1 christos
418 1.1 christos result = memman_alloc(aml_memman, memid_aml_local_stack);
419 1.1 christos memset(result, 0, sizeof(struct aml_local_stack));
420 1.1 christos return (result);
421 1.1 christos }
422 1.1 christos
423 1.1 christos void
424 1.1 christos aml_local_stack_push(struct aml_local_stack *stack)
425 1.1 christos {
426 1.1 christos
427 1.1 christos stack->next = stack_top;
428 1.1 christos stack_top = stack;
429 1.1 christos }
430 1.1 christos
431 1.1 christos struct aml_local_stack *
432 1.1 christos aml_local_stack_pop()
433 1.1 christos {
434 1.1 christos struct aml_local_stack *result;
435 1.1 christos
436 1.1 christos result = stack_top;
437 1.1 christos stack_top = result->next;
438 1.1 christos result->next = NULL;
439 1.1 christos return (result);
440 1.1 christos }
441 1.1 christos
442 1.1 christos void
443 1.1 christos aml_local_stack_delete(struct aml_local_stack *stack)
444 1.1 christos {
445 1.1 christos int i;
446 1.1 christos
447 1.1 christos for (i = 0; i < 8; i++)
448 1.1 christos aml_free_object(&stack->localvalue[i].property);
449 1.1 christos for (i = 0; i < 7; i++)
450 1.1 christos aml_free_object(&stack->argumentvalue[i].property);
451 1.1 christos aml_delete_name(stack->temporary);
452 1.1 christos memman_free(aml_memman, memid_aml_local_stack, stack);
453 1.1 christos }
454 1.1 christos
455 1.1 christos struct aml_name *
456 1.1 christos aml_local_stack_getLocalX(int idx)
457 1.1 christos {
458 1.1 christos
459 1.1 christos if (stack_top == NULL)
460 1.1 christos return (NULL);
461 1.1 christos return (&stack_top->localvalue[idx]);
462 1.1 christos }
463 1.1 christos
464 1.1 christos struct aml_name *
465 1.1 christos aml_local_stack_getArgX(struct aml_local_stack *stack, int idx)
466 1.1 christos {
467 1.1 christos
468 1.1 christos if (!stack)
469 1.1 christos stack = stack_top;
470 1.1 christos if (stack == NULL)
471 1.1 christos return (NULL);
472 1.1 christos return (&stack->argumentvalue[idx]);
473 1.1 christos }
474 1.1 christos
475 1.1 christos struct aml_name *
476 1.1 christos aml_create_local_object()
477 1.1 christos {
478 1.1 christos struct aml_name *result;
479 1.1 christos
480 1.1 christos result = memman_alloc(aml_memman, memid_aml_name);
481 1.1 christos result->child = result->brother = result->parent = NULL;
482 1.1 christos result->property = NULL;
483 1.1 christos result->chain = stack_top->temporary;
484 1.1 christos stack_top->temporary = result;
485 1.1 christos return (result);
486 1.1 christos }
487