1 /* $NetBSD: aml_name.c,v 1.3 2008/01/15 19:08:00 jmcneill Exp $ */
4 * Copyright (c) 1999 Takanori Watanabe
5 * Copyright (c) 1999, 2000 Yasuo Yokoyama
6 * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * Id: aml_name.c,v 1.15 2000/08/16 18:14:53 iwasaki Exp
31 * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_name.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: aml_name.c,v 1.3 2008/01/15 19:08:00 jmcneill Exp $");
36 #include <sys/param.h>
38 #include <acpi_common.h>
39 #include <aml/aml_amlmem.h>
40 #include <aml/aml_common.h>
41 #include <aml/aml_env.h>
42 #include <aml/aml_name.h>
51 #include <sys/systm.h>
54 static struct aml_name
*aml_find_name(struct aml_name
*, const u_int8_t
*);
55 static struct aml_name
*aml_new_name(struct aml_name
*, const u_int8_t
*);
56 static void aml_delete_name(struct aml_name
*);
58 static struct aml_name rootname
= {"\\", NULL
, NULL
, NULL
, NULL
, NULL
};
60 static struct aml_name_group root_group
= {
66 struct aml_name_group
*name_group_list
= &root_group
;
67 struct aml_local_stack
*stack_top
= NULL
;
76 static struct aml_name
*
77 aml_find_name(struct aml_name
*parent
, const u_int8_t
*name
)
79 struct aml_name
*result
;
83 for (result
= parent
->child
; result
; result
= result
->brother
)
84 if (!strncmp(result
->name
, (const char *)name
, 4))
90 * Parse given namesppace expression and find a first matched object
91 * under given level of the tree by depth first search.
95 aml_find_from_namespace(struct aml_name
*parent
, const char *name
)
99 struct aml_name
*result
;
105 if (ptr
[0] == '\\') {
109 for (len
= 0; ptr
[len
] != '.' && ptr
[len
] != '\0'; len
++)
112 for (result
= parent
->child
; result
; result
= result
->brother
) {
113 if (!strncmp(result
->name
, ptr
, len
)) {
114 if (ptr
[len
] == '\0' || ptr
[len
+ 1] == '\0') {
122 return (aml_find_from_namespace(result
, ptr
));
130 _aml_apply_foreach_found_objects(struct aml_name
*parent
, char *name
,
131 int len
, int shallow
, int (*func
)(struct aml_name
*, va_list), va_list ap
)
133 struct aml_name
*child
, *ptr
;
137 /* function to apply must be specified */
142 for (child
= parent
->child
; child
; child
= child
->brother
) {
143 if (!strncmp(child
->name
, name
, len
)) {
144 /* if function call was failed, stop searching */
145 if (func(child
, ap
) != 0) {
155 for (ptr
= parent
->child
; ptr
; ptr
= ptr
->brother
) {
156 /* do more searching */
157 _aml_apply_foreach_found_objects(ptr
, name
, len
, 0, func
, ap
);
162 * Find named objects as many as possible under given level of
163 * namespace, and apply given callback function for each
164 * named objects found. If the callback function returns non-zero
165 * value, then the search terminates immediately.
166 * Note that object name expression is used as forward substring match,
167 * not exact match. The name expression "_L" will match for objects
168 * which have name starting with "_L" such as "\_SB_.LID_._LID" and
169 * "\_GPE._L00" and so on. The name expression can include parent object
170 * name in it like "\_GPE._L". In this case, GPE X level wake handlers
171 * will be found under "\_GPE" in shallow level.
175 aml_apply_foreach_found_objects(struct aml_name
*start
, char *name
,
176 int (*func
)(struct aml_name
*, va_list), ...)
178 int i
, len
, has_dot
, last_is_dot
, shallow
;
179 struct aml_name
*child
, *parent
;
188 if (name
[0] == '\\') {
196 /* the last dot should be ignored */
197 if (len
> 0 && name
[len
- 1] == '.') {
203 for (i
= 0; i
< len
- 1; i
++) {
204 if (name
[i
] == '.') {
210 /* try to parse expression and find any matched object. */
212 child
= aml_find_from_namespace(parent
, name
);
218 * we have at least one object matched, search all objects
219 * under upper level of the found object.
221 parent
= child
->parent
;
223 /* find the last `.' */
224 for (name
= name
+ len
- 1; *name
!= '.'; name
--)
227 len
= strlen(name
) - last_is_dot
;
236 _aml_apply_foreach_found_objects(parent
, name
, len
, shallow
, func
, ap
);
240 struct aml_name_group
*
241 aml_new_name_group(void *id
)
243 struct aml_name_group
*result
;
245 result
= memman_alloc(aml_memman
, memid_aml_name_group
);
248 result
->next
= name_group_list
;
249 name_group_list
= result
;
254 aml_delete_name_group(struct aml_name_group
*target
)
256 struct aml_name_group
*previous
;
258 previous
= name_group_list
;
259 if (previous
== target
)
260 name_group_list
= target
->next
;
262 while (previous
&& previous
->next
!= target
)
263 previous
= previous
->next
;
265 previous
->next
= target
->next
;
269 aml_delete_name(target
->head
);
270 memman_free(aml_memman
, memid_aml_name_group
, target
);
273 static struct aml_name
*
274 aml_new_name(struct aml_name
*parent
, const u_int8_t
*name
)
276 struct aml_name
*newname
;
278 if ((newname
= aml_find_name(parent
, name
)) != NULL
)
281 newname
= memman_alloc(aml_memman
, memid_aml_name
);
282 strncpy(newname
->name
, (const char *)name
, 4);
283 newname
->parent
= parent
;
284 newname
->child
= NULL
;
285 newname
->property
= NULL
;
286 if (parent
&& parent
->child
)
287 newname
->brother
= parent
->child
;
289 newname
->brother
= NULL
;
291 parent
->child
= newname
;
293 newname
->chain
= name_group_list
->head
;
294 name_group_list
->head
= newname
;
301 * aml_delete_name() doesn't maintain aml_name_group::{head,tail}.
304 aml_delete_name(struct aml_name
*target
)
306 struct aml_name
*next
;
307 struct aml_name
*ptr
;
309 for (; target
; target
= next
) {
310 next
= target
->chain
;
312 target
->chain
= NULL
;
315 if (target
->brother
) {
316 if (target
->parent
) {
317 if (target
->parent
->child
== target
) {
318 target
->parent
->child
= target
->brother
;
320 ptr
= target
->parent
->child
;
321 while (ptr
&& ptr
->brother
!= target
)
324 ptr
->brother
= target
->brother
;
326 target
->brother
= NULL
;
328 } else if (target
->parent
) {
329 target
->parent
->child
= NULL
;
331 aml_free_object(&target
->property
);
332 memman_free(aml_memman
, memid_aml_name
, target
);
336 #define AML_SEARCH_NAME 0
337 #define AML_CREATE_NAME 1
338 static struct aml_name
*aml_nameman(struct aml_environ
*, const u_int8_t
*, int);
341 aml_search_name(struct aml_environ
*env
, const u_int8_t
*dp
)
344 return (aml_nameman(env
, dp
, AML_SEARCH_NAME
));
348 aml_create_name(struct aml_environ
*env
, const u_int8_t
*dp
)
351 return (aml_nameman(env
, dp
, AML_CREATE_NAME
));
354 static struct aml_name
*
355 aml_nameman(struct aml_environ
*env
, const u_int8_t
*dp
, int flag
)
359 struct aml_name
*newname
, *curname
;
360 struct aml_name
*(*searchfunc
) (struct aml_name
*, const u_int8_t
*);
362 #define CREATECHECK() do { \
363 if (newname == NULL) { \
364 AML_DEBUGPRINT("ERROR CANNOT FIND NAME\n"); \
365 env->stat = aml_stat_panic; \
370 searchfunc
= (flag
== AML_CREATE_NAME
) ? aml_new_name
: aml_find_name
;
371 newname
= env
->curname
;
375 } else if (dp
[0] == '^') {
376 while (dp
[0] == '^') {
377 newname
= newname
->parent
;
382 if (dp
[0] == 0x00) { /* NullName */
384 } else if (dp
[0] == 0x2e) { /* DualNamePrefix */
385 newname
= (*searchfunc
) (newname
, dp
+ 1);
387 newname
= (*searchfunc
) (newname
, dp
+ 5);
389 } else if (dp
[0] == 0x2f) { /* MultiNamePrefix */
391 for (i
= 0, dp
+= 2; i
< segcount
; i
++, dp
+= 4) {
392 newname
= (*searchfunc
) (newname
, dp
);
395 } else if (flag
== AML_CREATE_NAME
) { /* NameSeg */
396 newname
= aml_new_name(newname
, dp
);
401 newname
= aml_find_name(curname
, dp
);
404 if (curname
== &rootname
|| curname
== NULL
)
406 curname
= curname
->parent
;
414 struct aml_local_stack
*
415 aml_local_stack_create()
417 struct aml_local_stack
*result
;
419 result
= memman_alloc(aml_memman
, memid_aml_local_stack
);
420 memset(result
, 0, sizeof(struct aml_local_stack
));
425 aml_local_stack_push(struct aml_local_stack
*stack
)
428 stack
->next
= stack_top
;
432 struct aml_local_stack
*
433 aml_local_stack_pop()
435 struct aml_local_stack
*result
;
438 stack_top
= result
->next
;
444 aml_local_stack_delete(struct aml_local_stack
*stack
)
448 for (i
= 0; i
< 8; i
++)
449 aml_free_object(&stack
->localvalue
[i
].property
);
450 for (i
= 0; i
< 7; i
++)
451 aml_free_object(&stack
->argumentvalue
[i
].property
);
452 aml_delete_name(stack
->temporary
);
453 memman_free(aml_memman
, memid_aml_local_stack
, stack
);
457 aml_local_stack_getLocalX(int idx
)
460 if (stack_top
== NULL
)
462 return (&stack_top
->localvalue
[idx
]);
466 aml_local_stack_getArgX(struct aml_local_stack
*stack
, int idx
)
473 return (&stack
->argumentvalue
[idx
]);
477 aml_create_local_object()
479 struct aml_name
*result
;
481 result
= memman_alloc(aml_memman
, memid_aml_name
);
482 result
->child
= result
->brother
= result
->parent
= NULL
;
483 result
->property
= NULL
;
484 result
->chain
= stack_top
->temporary
;
485 stack_top
->temporary
= result
;