1 /* $NetBSD: acpi_util.c,v 1.5 2010/06/07 17:13:52 jruoho Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum of By Noon Software, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright 2001, 2003 Wasabi Systems, Inc. 34 * All rights reserved. 35 * 36 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed for the NetBSD Project by 49 * Wasabi Systems, Inc. 50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 51 * or promote products derived from this software without specific prior 52 * written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.5 2010/06/07 17:13:52 jruoho Exp $"); 69 70 #include <sys/param.h> 71 72 #include <dev/acpi/acpireg.h> 73 #include <dev/acpi/acpivar.h> 74 75 #define _COMPONENT ACPI_BUS_COMPONENT 76 ACPI_MODULE_NAME ("acpi_util") 77 78 static void acpi_clean_node(ACPI_HANDLE, void *); 79 80 /* 81 * Evaluate an integer object. 82 */ 83 ACPI_STATUS 84 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 85 { 86 ACPI_OBJECT obj; 87 ACPI_BUFFER buf; 88 ACPI_STATUS rv; 89 90 if (handle == NULL) 91 handle = ACPI_ROOT_OBJECT; 92 93 buf.Pointer = &obj; 94 buf.Length = sizeof(obj); 95 96 rv = AcpiEvaluateObject(handle, path, NULL, &buf); 97 98 if (ACPI_FAILURE(rv)) 99 return rv; 100 101 if (obj.Type != ACPI_TYPE_INTEGER) 102 return AE_TYPE; 103 104 if (valp != NULL) 105 *valp = obj.Integer.Value; 106 107 return AE_OK; 108 } 109 110 /* 111 * Evaluate an integer object with a single integer input parameter. 112 */ 113 ACPI_STATUS 114 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) 115 { 116 ACPI_OBJECT_LIST arg; 117 ACPI_OBJECT obj; 118 119 if (handle == NULL) 120 handle = ACPI_ROOT_OBJECT; 121 122 obj.Type = ACPI_TYPE_INTEGER; 123 obj.Integer.Value = val; 124 125 arg.Count = 1; 126 arg.Pointer = &obj; 127 128 return AcpiEvaluateObject(handle, path, &arg, NULL); 129 } 130 131 /* 132 * Evaluate a (Unicode) string object. 133 */ 134 ACPI_STATUS 135 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 136 { 137 ACPI_OBJECT *obj; 138 ACPI_BUFFER buf; 139 ACPI_STATUS rv; 140 141 rv = acpi_eval_struct(handle, path, &buf); 142 143 if (ACPI_FAILURE(rv)) 144 return rv; 145 146 obj = buf.Pointer; 147 148 if (obj->Type != ACPI_TYPE_STRING) { 149 rv = AE_TYPE; 150 goto out; 151 } 152 153 if (obj->String.Length == 0) { 154 rv = AE_BAD_DATA; 155 goto out; 156 } 157 158 *stringp = ACPI_ALLOCATE(obj->String.Length + 1); 159 160 if (*stringp == NULL) { 161 rv = AE_NO_MEMORY; 162 goto out; 163 } 164 165 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); 166 167 (*stringp)[obj->String.Length] = '\0'; 168 169 out: 170 ACPI_FREE(buf.Pointer); 171 172 return rv; 173 } 174 175 /* 176 * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). 177 */ 178 ACPI_STATUS 179 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) 180 { 181 182 if (handle == NULL) 183 handle = ACPI_ROOT_OBJECT; 184 185 buf->Pointer = NULL; 186 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 187 188 return AcpiEvaluateObject(handle, path, NULL, buf); 189 } 190 191 /* 192 * Evaluate a reference handle from an element in a package. 193 */ 194 ACPI_STATUS 195 acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) 196 { 197 198 if (elm == NULL || handle == NULL) 199 return AE_BAD_PARAMETER; 200 201 switch (elm->Type) { 202 203 case ACPI_TYPE_ANY: 204 case ACPI_TYPE_LOCAL_REFERENCE: 205 206 if (elm->Reference.Handle == NULL) 207 return AE_NULL_ENTRY; 208 209 *handle = elm->Reference.Handle; 210 211 return AE_OK; 212 213 case ACPI_TYPE_STRING: 214 return AcpiGetHandle(NULL, elm->String.Pointer, handle); 215 216 default: 217 return AE_TYPE; 218 } 219 } 220 221 /* 222 * Iterate over all objects in a package, and pass them all 223 * to a function. If the called function returns non-AE_OK, 224 * the iteration is stopped and that value is returned. 225 */ 226 ACPI_STATUS 227 acpi_foreach_package_object(ACPI_OBJECT *pkg, 228 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) 229 { 230 ACPI_STATUS rv = AE_OK; 231 uint32_t i; 232 233 if (pkg == NULL) 234 return AE_BAD_PARAMETER; 235 236 if (pkg->Type != ACPI_TYPE_PACKAGE) 237 return AE_TYPE; 238 239 for (i = 0; i < pkg->Package.Count; i++) { 240 241 rv = (*func)(&pkg->Package.Elements[i], arg); 242 243 if (ACPI_FAILURE(rv)) 244 break; 245 } 246 247 return rv; 248 } 249 250 /* 251 * Fetch data info the specified (empty) ACPI buffer. 252 * Caller must free buf.Pointer by ACPI_FREE(). 253 */ 254 ACPI_STATUS 255 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 256 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 257 { 258 259 buf->Pointer = NULL; 260 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 261 262 return (*getit)(handle, buf); 263 } 264 265 /* 266 * Get a device node from a handle. 267 */ 268 struct acpi_devnode * 269 acpi_get_node(ACPI_HANDLE handle) 270 { 271 struct acpi_devnode *ad; 272 ACPI_STATUS rv; 273 274 if (handle == NULL) 275 return NULL; 276 277 rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); 278 279 if (ACPI_FAILURE(rv)) 280 return NULL; 281 282 return ad; 283 } 284 285 /* 286 * Associate a device node with a handle. 287 */ 288 void 289 acpi_set_node(struct acpi_devnode *ad) 290 { 291 292 (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); 293 } 294 295 static void 296 acpi_clean_node(ACPI_HANDLE handle, void *aux) 297 { 298 /* Nothing. */ 299 } 300 301 /* 302 * Return a complete pathname from a handle. 303 * 304 * Note that the function uses static data storage; 305 * if the data is needed for future use, it should be 306 * copied before any subsequent calls overwrite it. 307 */ 308 const char * 309 acpi_name(ACPI_HANDLE handle) 310 { 311 static char name[80]; 312 ACPI_BUFFER buf; 313 ACPI_STATUS rv; 314 315 if (handle == NULL) 316 handle = ACPI_ROOT_OBJECT; 317 318 buf.Pointer = name; 319 buf.Length = sizeof(name); 320 321 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 322 323 if (ACPI_FAILURE(rv)) 324 return "UNKNOWN"; 325 326 return name; 327 } 328 329 /* 330 * Match given IDs against _HID and _CIDs. 331 */ 332 int 333 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 334 { 335 uint32_t i, n; 336 char *id; 337 338 while (*ids) { 339 340 if ((ad->Valid & ACPI_VALID_HID) != 0) { 341 342 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) 343 return 1; 344 } 345 346 if ((ad->Valid & ACPI_VALID_CID) != 0) { 347 348 n = ad->CompatibleIdList.Count; 349 350 for (i = 0; i < n; i++) { 351 352 id = ad->CompatibleIdList.Ids[i].String; 353 354 if (pmatch(id, *ids, NULL) == 2) 355 return 1; 356 } 357 } 358 359 ids++; 360 } 361 362 return 0; 363 } 364 365