1 /*        $NetBSD: aml_obj.c,v 1.2 2009/01/18 09:46:59 lukem 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_obj.c,v 1.17 2000/08/12 15:20:45 iwasaki Exp
30  *        $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_obj.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $
31  */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_obj.c,v 1.2 2009/01/18 09:46:59 lukem Exp $");
34 
35 #include <sys/param.h>
36 
37 #include <acpi_common.h>
38 #include <aml/aml_amlmem.h>
39 #include <aml/aml_env.h>
40 #include <aml/aml_name.h>
41 #include <aml/aml_obj.h>
42 #include <aml/aml_status.h>
43 #include <aml/aml_store.h>
44 
45 #ifndef _KERNEL
46 #include <sys/stat.h>
47 #include <sys/mman.h>
48 
49 #include <assert.h>
50 #include <err.h>
51 #include <fcntl.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #else /* _KERNEL */
56 #include <sys/systm.h>
57 #endif /* !_KERNEL */
58 
59 union aml_object *
aml_copy_object(struct aml_environ * env,union aml_object * orig)60 aml_copy_object(struct aml_environ *env, union aml_object *orig)
61 {
62           int       i;
63           union     aml_object *ret;
64 
65           if (orig == NULL)
66                     return (NULL);
67           switch (orig->type) {
68           case aml_t_regfield:
69                     ret = aml_alloc_object(aml_t_buffer, 0);
70                     ret->buffer.size = (orig->regfield.bitlen / 8) +
71                         ((orig->regfield.bitlen % 8) ? 1 : 0);
72                     if (ret->buffer.size == 0) {
73                               goto out;
74                     }
75                     ret->buffer.data = memman_alloc_flexsize(aml_memman, ret->buffer.size);
76                     aml_store_to_object(env, orig, ret);
77                     break;
78 
79           default:
80                     ret = aml_alloc_object(0, orig);
81                     break;
82           }
83 
84           if (1 || orig != &env->tempobject) {    /* XXX */
85                     if (orig->type == aml_t_buffer) {
86                               if (orig->buffer.size == 0) {
87                                         goto out;
88                               }
89                               ret->buffer.data = memman_alloc_flexsize(aml_memman,
90                                   orig->buffer.size);
91                               bcopy(orig->buffer.data, ret->buffer.data, orig->buffer.size);
92                     } else if (orig->type == aml_t_package) {
93                               if (ret->package.elements == 0) {
94                                         goto out;
95                               }
96                               ret->package.objects = memman_alloc_flexsize(aml_memman,
97                                   ret->package.elements * sizeof(union aml_object *));
98                               for (i = 0; i < ret->package.elements; i++) {
99                                         ret->package.objects[i] = aml_copy_object(env, orig->package.objects[i]);
100                               }
101                     } else if (orig->type == aml_t_string && orig->str.needfree != 0) {
102                               ret->str.string = memman_alloc_flexsize(aml_memman,
103                                   strlen((const char *)orig->str.string) + 1);
104                               strcpy((char *)orig->str.string,
105                                   (const char *)ret->str.string);
106                     } else if (orig->type == aml_t_num) {
107                         ret->num.constant = 0;
108                 }
109           } else {
110                     printf("%s:%d\n", __FILE__, __LINE__);
111                     env->tempobject.type = aml_t_null;
112           }
113 out:
114           return ret;
115 }
116 
117 /*
118  * This function have two function: copy or allocate.  if orig != NULL,
119  *  orig is duplicated.
120  */
121 
122 union aml_object *
aml_alloc_object(enum aml_objtype type,union aml_object * orig)123 aml_alloc_object(enum aml_objtype type, union aml_object *orig)
124 {
125           unsigned  int memid;
126           union     aml_object *ret;
127 
128           if (orig != NULL) {
129                     type = orig->type;
130           }
131           switch (type) {
132           case aml_t_namestr:
133                     memid = memid_aml_namestr;
134                     break;
135           case aml_t_buffer:
136                     memid = memid_aml_buffer;
137                     break;
138           case aml_t_string:
139                     memid = memid_aml_string;
140                     break;
141           case aml_t_bufferfield:
142                     memid = memid_aml_bufferfield;
143                     break;
144           case aml_t_package:
145                     memid = memid_aml_package;
146                     break;
147           case aml_t_num:
148                     memid = memid_aml_num;
149                     break;
150           case aml_t_powerres:
151                     memid = memid_aml_powerres;
152                     break;
153           case aml_t_opregion:
154                     memid = memid_aml_opregion;
155                     break;
156           case aml_t_method:
157                     memid = memid_aml_method;
158                     break;
159           case aml_t_processor:
160                     memid = memid_aml_processor;
161                     break;
162           case aml_t_field:
163                     memid = memid_aml_field;
164                     break;
165           case aml_t_mutex:
166                     memid = memid_aml_mutex;
167                     break;
168           case aml_t_device:
169                     memid = memid_aml_objtype;
170                     break;
171           case aml_t_objref:
172                     memid = memid_aml_objref;
173                     break;
174           default:
175                     memid = memid_aml_objtype;
176                     break;
177           }
178           ret = memman_alloc(aml_memman, memid);
179           ret->type = type;
180 
181           if (orig != NULL) {
182                     bcopy(orig, ret, memman_memid2size(aml_memman, memid));
183           }
184           return (ret);
185 }
186 
187 void
aml_free_objectcontent(union aml_object * obj)188 aml_free_objectcontent(union aml_object *obj)
189 {
190           int       i;
191 
192           if (obj->type == aml_t_buffer && obj->buffer.data != NULL) {
193                     memman_free_flexsize(aml_memman, obj->buffer.data);
194                     obj->buffer.data = NULL;
195           }
196           if (obj->type == aml_t_string && obj->str.string != NULL) {
197                     if (obj->str.needfree != 0) {
198                               memman_free_flexsize(aml_memman, obj->str.string);
199                               obj->str.string = NULL;
200                     }
201           }
202           if (obj->type == aml_t_package && obj->package.objects != NULL) {
203                     for (i = 0; i < obj->package.elements; i++) {
204                               aml_free_object(&obj->package.objects[i]);
205                     }
206                     memman_free_flexsize(aml_memman, obj->package.objects);
207                     obj->package.objects = NULL;
208           }
209 }
210 
211 void
aml_free_object(union aml_object ** obj)212 aml_free_object(union aml_object **obj)
213 {
214           union     aml_object *body;
215 
216           body = *obj;
217           if (body == NULL) {
218                     return;
219           }
220           aml_free_objectcontent(*obj);
221           memman_free(aml_memman, memid_unkown, *obj);
222           *obj = NULL;
223 }
224 
225 void
aml_realloc_object(union aml_object * obj,int size)226 aml_realloc_object(union aml_object *obj, int size)
227 {
228           int       i;
229           enum      aml_objtype type;
230           union     aml_object tmp;
231 
232           type = obj->type;
233           switch (type) {
234           case aml_t_buffer:
235                     if (obj->buffer.size >= size) {
236                               return;
237                     }
238                     tmp.buffer.size = size;
239                     tmp.buffer.data = memman_alloc_flexsize(aml_memman, size);
240                     bzero(tmp.buffer.data, size);
241                     bcopy(obj->buffer.data, tmp.buffer.data, obj->buffer.size);
242                     aml_free_objectcontent(obj);
243                     *obj = tmp;
244                     break;
245           case aml_t_string:
246                     if ((int)strlen((const char *)obj->str.string) >= size) {
247                               return;
248                     }
249                     tmp.str.string = memman_alloc_flexsize(aml_memman, size + 1);
250                     strcpy((char *)tmp.str.string, (const char *)obj->str.string);
251                     aml_free_objectcontent(obj);
252                     *obj = tmp;
253                     break;
254           case aml_t_package:
255                     if (obj->package.elements >= size) {
256                               return;
257                     }
258                     tmp.package.objects = memman_alloc_flexsize(aml_memman,
259                         size * sizeof(union aml_object *));
260                     bzero(tmp.package.objects, size * sizeof(union aml_object *));
261                     for (i = 0; i < obj->package.elements; i++) {
262                               tmp.package.objects[i] = obj->package.objects[i];
263                     }
264                     memman_free_flexsize(aml_memman, obj->package.objects);
265                     obj->package.objects = tmp.package.objects;
266                     break;
267           default:
268                     break;
269           }
270 }
271