1 /* $NetBSD: acpi_util.c,v 1.6 2010/11/02 16:45:48 gsutre 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.6 2010/11/02 16:45:48 gsutre 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 (void)memset(&obj, 0, sizeof(obj)); 94 buf.Pointer = &obj; 95 buf.Length = sizeof(obj); 96 97 rv = AcpiEvaluateObject(handle, path, NULL, &buf); 98 99 if (ACPI_FAILURE(rv)) 100 return rv; 101 102 /* Check that evaluation produced a return value. */ 103 if (buf.Length == 0) 104 return AE_NULL_OBJECT; 105 106 if (obj.Type != ACPI_TYPE_INTEGER) 107 return AE_TYPE; 108 109 if (valp != NULL) 110 *valp = obj.Integer.Value; 111 112 return AE_OK; 113 } 114 115 /* 116 * Evaluate an integer object with a single integer input parameter. 117 */ 118 ACPI_STATUS 119 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) 120 { 121 ACPI_OBJECT_LIST arg; 122 ACPI_OBJECT obj; 123 124 if (handle == NULL) 125 handle = ACPI_ROOT_OBJECT; 126 127 obj.Type = ACPI_TYPE_INTEGER; 128 obj.Integer.Value = val; 129 130 arg.Count = 1; 131 arg.Pointer = &obj; 132 133 return AcpiEvaluateObject(handle, path, &arg, NULL); 134 } 135 136 /* 137 * Evaluate a (Unicode) string object. 138 */ 139 ACPI_STATUS 140 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 141 { 142 ACPI_OBJECT *obj; 143 ACPI_BUFFER buf; 144 ACPI_STATUS rv; 145 146 rv = acpi_eval_struct(handle, path, &buf); 147 148 if (ACPI_FAILURE(rv)) 149 return rv; 150 151 obj = buf.Pointer; 152 153 if (obj->Type != ACPI_TYPE_STRING) { 154 rv = AE_TYPE; 155 goto out; 156 } 157 158 if (obj->String.Length == 0) { 159 rv = AE_BAD_DATA; 160 goto out; 161 } 162 163 *stringp = ACPI_ALLOCATE(obj->String.Length + 1); 164 165 if (*stringp == NULL) { 166 rv = AE_NO_MEMORY; 167 goto out; 168 } 169 170 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); 171 172 (*stringp)[obj->String.Length] = '\0'; 173 174 out: 175 ACPI_FREE(buf.Pointer); 176 177 return rv; 178 } 179 180 /* 181 * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). 182 */ 183 ACPI_STATUS 184 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) 185 { 186 187 if (handle == NULL) 188 handle = ACPI_ROOT_OBJECT; 189 190 buf->Pointer = NULL; 191 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 192 193 return AcpiEvaluateObject(handle, path, NULL, buf); 194 } 195 196 /* 197 * Evaluate a reference handle from an element in a package. 198 */ 199 ACPI_STATUS 200 acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) 201 { 202 203 if (elm == NULL || handle == NULL) 204 return AE_BAD_PARAMETER; 205 206 switch (elm->Type) { 207 208 case ACPI_TYPE_ANY: 209 case ACPI_TYPE_LOCAL_REFERENCE: 210 211 if (elm->Reference.Handle == NULL) 212 return AE_NULL_ENTRY; 213 214 *handle = elm->Reference.Handle; 215 216 return AE_OK; 217 218 case ACPI_TYPE_STRING: 219 return AcpiGetHandle(NULL, elm->String.Pointer, handle); 220 221 default: 222 return AE_TYPE; 223 } 224 } 225 226 /* 227 * Iterate over all objects in a package, and pass them all 228 * to a function. If the called function returns non-AE_OK, 229 * the iteration is stopped and that value is returned. 230 */ 231 ACPI_STATUS 232 acpi_foreach_package_object(ACPI_OBJECT *pkg, 233 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) 234 { 235 ACPI_STATUS rv = AE_OK; 236 uint32_t i; 237 238 if (pkg == NULL) 239 return AE_BAD_PARAMETER; 240 241 if (pkg->Type != ACPI_TYPE_PACKAGE) 242 return AE_TYPE; 243 244 for (i = 0; i < pkg->Package.Count; i++) { 245 246 rv = (*func)(&pkg->Package.Elements[i], arg); 247 248 if (ACPI_FAILURE(rv)) 249 break; 250 } 251 252 return rv; 253 } 254 255 /* 256 * Fetch data info the specified (empty) ACPI buffer. 257 * Caller must free buf.Pointer by ACPI_FREE(). 258 */ 259 ACPI_STATUS 260 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 261 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 262 { 263 264 buf->Pointer = NULL; 265 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 266 267 return (*getit)(handle, buf); 268 } 269 270 /* 271 * Get a device node from a handle. 272 */ 273 struct acpi_devnode * 274 acpi_get_node(ACPI_HANDLE handle) 275 { 276 struct acpi_devnode *ad; 277 ACPI_STATUS rv; 278 279 if (handle == NULL) 280 return NULL; 281 282 rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); 283 284 if (ACPI_FAILURE(rv)) 285 return NULL; 286 287 return ad; 288 } 289 290 /* 291 * Associate a device node with a handle. 292 */ 293 void 294 acpi_set_node(struct acpi_devnode *ad) 295 { 296 297 (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); 298 } 299 300 static void 301 acpi_clean_node(ACPI_HANDLE handle, void *aux) 302 { 303 /* Nothing. */ 304 } 305 306 /* 307 * Return a complete pathname from a handle. 308 * 309 * Note that the function uses static data storage; 310 * if the data is needed for future use, it should be 311 * copied before any subsequent calls overwrite it. 312 */ 313 const char * 314 acpi_name(ACPI_HANDLE handle) 315 { 316 static char name[80]; 317 ACPI_BUFFER buf; 318 ACPI_STATUS rv; 319 320 if (handle == NULL) 321 handle = ACPI_ROOT_OBJECT; 322 323 buf.Pointer = name; 324 buf.Length = sizeof(name); 325 326 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 327 328 if (ACPI_FAILURE(rv)) 329 return "UNKNOWN"; 330 331 return name; 332 } 333 334 /* 335 * Match given IDs against _HID and _CIDs. 336 */ 337 int 338 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 339 { 340 uint32_t i, n; 341 char *id; 342 343 while (*ids) { 344 345 if ((ad->Valid & ACPI_VALID_HID) != 0) { 346 347 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) 348 return 1; 349 } 350 351 if ((ad->Valid & ACPI_VALID_CID) != 0) { 352 353 n = ad->CompatibleIdList.Count; 354 355 for (i = 0; i < n; i++) { 356 357 id = ad->CompatibleIdList.Ids[i].String; 358 359 if (pmatch(id, *ids, NULL) == 2) 360 return 1; 361 } 362 } 363 364 ids++; 365 } 366 367 return 0; 368 } 369 370