Home | History | Annotate | Line # | Download | only in acpi
acpi.c revision 1.4.4.5
      1 /*	$NetBSD: acpi.c,v 1.4.4.5 2002/04/01 07:45:06 nathanw Exp $	*/
      2 
      3 /*
      4  * Copyright 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     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.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed for the NetBSD Project by
     20  *	Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * Autoconfiguration support for the Intel ACPI Component Architecture
     40  * ACPI reference implementation.
     41  */
     42 
     43 #include <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.4.4.5 2002/04/01 07:45:06 nathanw Exp $");
     45 
     46 #include <sys/param.h>
     47 #include <sys/systm.h>
     48 #include <sys/device.h>
     49 #include <sys/malloc.h>
     50 
     51 #include <dev/acpi/acpica.h>
     52 #include <dev/acpi/acpireg.h>
     53 #include <dev/acpi/acpivar.h>
     54 #include <dev/acpi/acpi_osd.h>
     55 
     56 #ifdef ENABLE_DEBUGGER
     57 #define	ACPI_DBGR_INIT		0x01
     58 #define	ACPI_DBGR_TABLES	0x02
     59 #define	ACPI_DBGR_ENABLE	0x04
     60 #define	ACPI_DBGR_PROBE		0x08
     61 #define	ACPI_DBGR_RUNNING	0x10
     62 
     63 int	acpi_dbgr = 0x00;
     64 #endif
     65 
     66 int	acpi_match(struct device *, struct cfdata *, void *);
     67 void	acpi_attach(struct device *, struct device *, void *);
     68 
     69 int	acpi_print(void *aux, const char *);
     70 
     71 extern struct cfdriver acpi_cd;
     72 
     73 struct cfattach acpi_ca = {
     74 	sizeof(struct acpi_softc), acpi_match, acpi_attach,
     75 };
     76 
     77 /*
     78  * This is a flag we set when the ACPI subsystem is active.  Machine
     79  * dependent code may wish to skip other steps (such as attaching
     80  * subsystems that ACPI supercedes) when ACPI is active.
     81  */
     82 int	acpi_active;
     83 
     84 /*
     85  * Pointer to the ACPI subsystem's state.  There can be only
     86  * one ACPI instance.
     87  */
     88 struct acpi_softc *acpi_softc;
     89 
     90 void		acpi_shutdown(void *);
     91 ACPI_STATUS	acpi_disable(struct acpi_softc *sc);
     92 void		acpi_build_tree(struct acpi_softc *);
     93 ACPI_STATUS	acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
     94 
     95 void		acpi_enable_fixed_events(struct acpi_softc *);
     96 
     97 /*
     98  * acpi_probe:
     99  *
    100  *	Probe for ACPI support.  This is called by the
    101  *	machine-dependent ACPI front-end.  All of the
    102  *	actual work is done by ACPICA.
    103  *
    104  *	NOTE: This is not an autoconfiguration interface function.
    105  */
    106 int
    107 acpi_probe(void)
    108 {
    109 	static int beenhere;
    110 	ACPI_STATUS rv;
    111 
    112 	if (beenhere != 0)
    113 		panic("acpi_probe: ACPI has already been probed");
    114 	beenhere = 1;
    115 
    116 	/*
    117 	 * Start up ACPICA.
    118 	 */
    119 #ifdef ENABLE_DEBUGGER
    120 	if (acpi_dbgr & ACPI_DBGR_INIT)
    121 		acpi_osd_debugger();
    122 #endif
    123 
    124 	rv = AcpiInitializeSubsystem();
    125 	if (rv != AE_OK) {
    126 		printf("ACPI: unable to initialize ACPICA: %d\n", rv);
    127 		return (0);
    128 	}
    129 
    130 #ifdef ENABLE_DEBUGGER
    131 	if (acpi_dbgr & ACPI_DBGR_TABLES)
    132 		acpi_osd_debugger();
    133 #endif
    134 
    135 	rv = AcpiLoadTables();
    136 	if (rv != AE_OK) {
    137 		printf("ACPI: unable to load tables: %d\n", rv);
    138 		return (0);
    139 	}
    140 
    141 	/*
    142 	 * Looks like we have ACPI!
    143 	 */
    144 
    145 	return (1);
    146 }
    147 
    148 /*
    149  * acpi_match:
    150  *
    151  *	Autoconfiguration `match' routine.
    152  */
    153 int
    154 acpi_match(struct device *parent, struct cfdata *match, void *aux)
    155 {
    156 	struct acpibus_attach_args *aa = aux;
    157 
    158 	if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
    159 		return (0);
    160 
    161 	/*
    162 	 * XXX Check other locators?  Hard to know -- machine
    163 	 * dependent code has already checked for the presence
    164 	 * of ACPI by calling acpi_probe(), so I suppose we
    165 	 * don't really have to do anything else.
    166 	 */
    167 	return (1);
    168 }
    169 
    170 /*
    171  * acpi_attach:
    172  *
    173  *	Autoconfiguration `attach' routine.  Finish initializing
    174  *	ACPICA (some initialization was done in acpi_probe(),
    175  *	which was required to check for the presence of ACPI),
    176  *	and enable the ACPI subsystem.
    177  */
    178 void
    179 acpi_attach(struct device *parent, struct device *self, void *aux)
    180 {
    181 	struct acpi_softc *sc = (void *) self;
    182 	struct acpibus_attach_args *aa = aux;
    183 	ACPI_STATUS rv;
    184 
    185 	printf("\n");
    186 
    187 	if (acpi_softc != NULL)
    188 		panic("acpi_attach: ACPI has already been attached");
    189 
    190 	sc->sc_iot = aa->aa_iot;
    191 	sc->sc_memt = aa->aa_memt;
    192 	sc->sc_pc = aa->aa_pc;
    193 	sc->sc_pciflags = aa->aa_pciflags;
    194 
    195 	acpi_softc = sc;
    196 
    197 	/*
    198 	 * Install the default address space handlers.
    199 	 */
    200 
    201 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    202 	    ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
    203 	if (rv != AE_OK) {
    204 		printf("%s: unable to install SYSTEM MEMORY handler: %d\n",
    205 		    sc->sc_dev.dv_xname, rv);
    206 		return;
    207 	}
    208 
    209 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    210 	    ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
    211 	if (rv != AE_OK) {
    212 		printf("%s: unable to install SYSTEM IO handler: %d\n",
    213 		    sc->sc_dev.dv_xname, rv);
    214 		return;
    215 	}
    216 
    217 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    218 	    ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
    219 	if (rv != AE_OK) {
    220 		printf("%s: unable to install PCI CONFIG handler: %d\n",
    221 		    sc->sc_dev.dv_xname, rv);
    222 		return;
    223 	}
    224 
    225 	/*
    226 	 * Bring ACPI on-line.
    227 	 *
    228 	 * Note that we request that _STA (device init) and _INI (object init)
    229 	 * methods not be run.
    230 	 *
    231 	 * XXX We need to arrange for the object init pass after we have
    232 	 * XXX attached all of our children.
    233 	 */
    234 #ifdef ENABLE_DEBUGGER
    235 	if (acpi_dbgr & ACPI_DBGR_ENABLE)
    236 		acpi_osd_debugger();
    237 #endif
    238 	rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
    239 	if (rv != AE_OK) {
    240 		printf("%s: unable to enable ACPI: %d\n",
    241 		    sc->sc_dev.dv_xname, rv);
    242 		return;
    243 	}
    244 	acpi_active = 1;
    245 
    246 	/*
    247 	 * Set up the default sleep state to enter when various
    248 	 * switches are activated.
    249 	 */
    250 	sc->sc_switch_sleep[ACPI_SWITCH_POWERBUTTON] = ACPI_STATE_S5;
    251 	sc->sc_switch_sleep[ACPI_SWITCH_SLEEPBUTTON] = ACPI_STATE_S1;
    252 	sc->sc_switch_sleep[ACPI_SWITCH_LID]	     = ACPI_STATE_S1;
    253 
    254 	/* Our current state is "awake". */
    255 	sc->sc_sleepstate = ACPI_STATE_S0;
    256 
    257 	/*
    258 	 * Check for fixed-hardware features.
    259 	 */
    260 	acpi_enable_fixed_events(sc);
    261 
    262 	/*
    263 	 * Scan the namespace and build our device tree.
    264 	 */
    265 #ifdef ENABLE_DEBUGGER
    266 	if (acpi_dbgr & ACPI_DBGR_PROBE)
    267 		acpi_osd_debugger();
    268 #endif
    269 	acpi_build_tree(sc);
    270 
    271 	/*
    272 	 * Register a shutdown hook that disables certain ACPI
    273 	 * events that might happen and confuse us while we're
    274 	 * trying to shut down.
    275 	 */
    276 	sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
    277 	if (sc->sc_sdhook == NULL)
    278 		printf("%s: WARNING: unable to register shutdown hook\n",
    279 		    sc->sc_dev.dv_xname);
    280 
    281 #ifdef ENABLE_DEBUGGER
    282 	if (acpi_dbgr & ACPI_DBGR_RUNNING)
    283 		acpi_osd_debugger();
    284 #endif
    285 }
    286 
    287 /*
    288  * acpi_shutdown:
    289  *
    290  *	Shutdown hook for ACPI -- disable some events that
    291  *	might confuse us.
    292  */
    293 void
    294 acpi_shutdown(void *arg)
    295 {
    296 	struct acpi_softc *sc = arg;
    297 
    298 	if (acpi_disable(sc) != AE_OK)
    299 		printf("%s: WARNING: unable to disable ACPI\n",
    300 		    sc->sc_dev.dv_xname);
    301 }
    302 
    303 /*
    304  * acpi_disable:
    305  *
    306  *	Disable ACPI.
    307  */
    308 ACPI_STATUS
    309 acpi_disable(struct acpi_softc *sc)
    310 {
    311 	ACPI_STATUS rv = AE_OK;
    312 
    313 	if (acpi_active) {
    314 		rv = AcpiDisable();
    315 		if (rv == AE_OK)
    316 			acpi_active = 0;
    317 	}
    318 	return (rv);
    319 }
    320 
    321 struct acpi_make_devnode_state {
    322 	struct acpi_softc *softc;
    323 	struct acpi_scope *scope;
    324 };
    325 
    326 /*
    327  * acpi_build_tree:
    328  *
    329  *	Scan relevant portions of the ACPI namespace and attach
    330  *	child devices.
    331  */
    332 void
    333 acpi_build_tree(struct acpi_softc *sc)
    334 {
    335 	static const char *scopes[] = {
    336 		"\\_PR_",	/* ACPI 1.0 processor namespace */
    337 		"\\_SB_",	/* system bus namespace */
    338 		"\\_SI_",	/* system idicator namespace */
    339 		"\\_TZ_",	/* ACPI 1.0 thermal zone namespace */
    340 		NULL,
    341 	};
    342 	struct acpi_attach_args aa;
    343 	struct acpi_make_devnode_state state;
    344 	struct acpi_scope *as;
    345 	struct acpi_devnode *ad;
    346 	ACPI_HANDLE parent;
    347 	int i;
    348 
    349 	TAILQ_INIT(&sc->sc_scopes);
    350 
    351 	state.softc = sc;
    352 
    353 	/*
    354 	 * Scan the namespace and build our tree.
    355 	 */
    356 	for (i = 0; scopes[i] != NULL; i++) {
    357 		as = malloc(sizeof(*as), M_DEVBUF, M_WAITOK);
    358 		as->as_name = scopes[i];
    359 		TAILQ_INIT(&as->as_devnodes);
    360 
    361 		TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
    362 
    363 		state.scope = as;
    364 
    365 		if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
    366 		    &parent) == AE_OK) {
    367 			AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
    368 			    acpi_make_devnode, &state, NULL);
    369 		}
    370 
    371 		/* Now, for this namespace, try and attach the devices. */
    372 		TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
    373 			aa.aa_node = ad;
    374 			aa.aa_iot = sc->sc_iot;
    375 			aa.aa_memt = sc->sc_memt;
    376 			aa.aa_pc = sc->sc_pc;
    377 			aa.aa_pciflags = sc->sc_pciflags;
    378 
    379 			/*
    380 			 * XXX We only attach devices which are:
    381 			 *
    382 			 *	- present
    383 			 *	- enabled
    384 			 *	- to be shown
    385 			 *	- functioning properly
    386 			 *
    387 			 * However, if enabled, it's decoding resources,
    388 			 * so we should claim them, if possible.  Requires
    389 			 * changes to bus_space(9).
    390 			 */
    391 			if ((ad->ad_devinfo.CurrentStatus &
    392 			     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
    393 			      ACPI_STA_DEV_SHOW|ACPI_STA_DEV_OK)) !=
    394 			    (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
    395 			     ACPI_STA_DEV_SHOW|ACPI_STA_DEV_OK))
    396 				continue;
    397 
    398 			/*
    399 			 * XXX Same problem as above...
    400 			 */
    401 			if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
    402 				continue;
    403 
    404 			ad->ad_device = config_found(&sc->sc_dev,
    405 			    &aa, acpi_print);
    406 		}
    407 	}
    408 }
    409 
    410 /*
    411  * acpi_make_devnode:
    412  *
    413  *	Make an ACPI devnode.
    414  */
    415 ACPI_STATUS
    416 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
    417     void **status)
    418 {
    419 	struct acpi_make_devnode_state *state = context;
    420 #ifdef ACPI_DEBUG
    421 	struct acpi_softc *sc = state->softc;
    422 #endif
    423 	struct acpi_scope *as = state->scope;
    424 	struct acpi_devnode *ad;
    425 	ACPI_OBJECT_TYPE type;
    426 	ACPI_STATUS rv;
    427 
    428 	if (AcpiGetType(handle, &type) == AE_OK) {
    429 		switch (type) {
    430 		case ACPI_TYPE_DEVICE:
    431 		case ACPI_TYPE_PROCESSOR:
    432 		case ACPI_TYPE_THERMAL:
    433 		case ACPI_TYPE_POWER:
    434 			ad = malloc(sizeof(*ad), M_DEVBUF, M_NOWAIT|M_ZERO);
    435 			if (ad == NULL)
    436 				return (AE_NO_MEMORY);
    437 
    438 			ad->ad_handle = handle;
    439 			ad->ad_level = level;
    440 			ad->ad_scope = as;
    441 			ad->ad_type = type;
    442 
    443 			TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
    444 
    445 			rv = AcpiGetObjectInfo(handle, &ad->ad_devinfo);
    446 			if (rv != AE_OK)
    447 				goto out;
    448 
    449 			if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
    450 				goto out;
    451 
    452 #ifdef ACPI_DEBUG
    453 			printf("%s: HID %s found in scope %s level %d\n",
    454 			    sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId,
    455 			    as->as_name, ad->ad_level);
    456 			if (ad->ad_devinfo.Valid & ACPI_VALID_UID)
    457 				printf("       UID %s\n",
    458 				    ad->ad_devinfo.UniqueId);
    459 			if (ad->ad_devinfo.Valid & ACPI_VALID_ADR)
    460 				printf("       ADR 0x%016qx\n",
    461 				    ad->ad_devinfo.Address);
    462 			if (ad->ad_devinfo.Valid & ACPI_VALID_STA)
    463 				printf("       STA 0x%08x\n",
    464 				    ad->ad_devinfo.CurrentStatus);
    465 #endif
    466 		}
    467 	}
    468  out:
    469 	return (AE_OK);
    470 }
    471 
    472 /*
    473  * acpi_print:
    474  *
    475  *	Autoconfiguration print routine.
    476  */
    477 int
    478 acpi_print(void *aux, const char *pnp)
    479 {
    480 	struct acpi_attach_args *aa = aux;
    481 #if 0
    482 	char *str;
    483 #endif
    484 
    485 	if (pnp) {
    486 		printf("%s ", aa->aa_node->ad_devinfo.HardwareId);
    487 #if 0 /* Not until we fix acpi_eval_string */
    488 		if (acpi_eval_string(aa->aa_node->ad_handle,
    489 		    "_STR", &str) == AE_OK) {
    490 			printf("[%s] ", str);
    491 			AcpiOsFree(str);
    492 		}
    493 #endif
    494 		printf("at %s", pnp);
    495 	}
    496 
    497 	return (UNCONF);
    498 }
    499 
    500 /*****************************************************************************
    501  * ACPI fixed-hardware feature handlers
    502  *****************************************************************************/
    503 
    504 UINT32		acpi_fixed_power_button_handler(void *);
    505 UINT32		acpi_fixed_sleep_button_handler(void *);
    506 
    507 /*
    508  * acpi_enable_fixed_events:
    509  *
    510  *	Enable any fixed-hardware feature handlers.
    511  */
    512 void
    513 acpi_enable_fixed_events(struct acpi_softc *sc)
    514 {
    515 	static int beenhere;
    516 	ACPI_STATUS rv;
    517 
    518 	/*
    519 	 * Check for fixed-hardware buttons.
    520 	 */
    521 
    522 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
    523 		if (beenhere == 0)
    524 			printf("%s: fixed-feature power button present\n",
    525 			    sc->sc_dev.dv_xname);
    526 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
    527 		    acpi_fixed_power_button_handler, sc);
    528 		if (rv != AE_OK)
    529 			printf("%s: unable to install handler for fixed "
    530 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    531 	}
    532 
    533 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
    534 		if (beenhere == 0)
    535 			printf("%s: fixed-feature sleep button present\n",
    536 			    sc->sc_dev.dv_xname);
    537 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
    538 		    acpi_fixed_sleep_button_handler, sc);
    539 		if (rv != AE_OK)
    540 			printf("%s: unable to install handler for fixed "
    541 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    542 	}
    543 
    544 	beenhere = 1;
    545 }
    546 
    547 /*
    548  * acpi_fixed_power_button_handler:
    549  *
    550  *	Fixed event handler for the power button.
    551  */
    552 UINT32
    553 acpi_fixed_power_button_handler(void *context)
    554 {
    555 	struct acpi_softc *sc = context;
    556 
    557 	/* XXX XXX XXX */
    558 
    559 	printf("%s: fixed power button pressed\n", sc->sc_dev.dv_xname);
    560 
    561 	return (INTERRUPT_HANDLED);
    562 }
    563 
    564 /*
    565  * acpi_fixed_sleep_button_handler:
    566  *
    567  *	Fixed event handler for the sleep button.
    568  */
    569 UINT32
    570 acpi_fixed_sleep_button_handler(void *context)
    571 {
    572 	struct acpi_softc *sc = context;
    573 
    574 	/* XXX XXX XXX */
    575 
    576 	printf("%s: fixed sleep button pressed\n", sc->sc_dev.dv_xname);
    577 
    578 	return (INTERRUPT_HANDLED);
    579 }
    580 
    581 /*****************************************************************************
    582  * ACPI utility routines.
    583  *****************************************************************************/
    584 
    585 /*
    586  * acpi_eval_integer:
    587  *
    588  *	Evaluate an integer object.
    589  */
    590 ACPI_STATUS
    591 acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
    592 {
    593 	ACPI_STATUS rv;
    594 	ACPI_BUFFER buf;
    595 	ACPI_OBJECT param;
    596 
    597 	if (handle == NULL)
    598 		handle = ACPI_ROOT_OBJECT;
    599 
    600 	buf.Pointer = &param;
    601 	buf.Length = sizeof(param);
    602 
    603 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    604 	if (rv == AE_OK) {
    605 		if (param.Type == ACPI_TYPE_INTEGER)
    606 			*valp = param.Integer.Value;
    607 		else
    608 			rv = AE_TYPE;
    609 	}
    610 
    611 	return (rv);
    612 }
    613 
    614 #if 0
    615 /*
    616  * acpi_eval_string:
    617  *
    618  *	Evaluate a (Unicode) string object.
    619  * XXX current API may leak memory, so don't use this.
    620  */
    621 ACPI_STATUS
    622 acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
    623 {
    624 	ACPI_STATUS rv;
    625 	ACPI_BUFFER buf;
    626 	ACPI_OBJECT *param;
    627 
    628 	if (handle == NULL)
    629 		handle = ACPI_ROOT_OBJECT;
    630 
    631 	buf.Pointer = NULL;
    632 	buf.Length = 0;
    633 
    634 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    635 	if (rv != AE_BUFFER_OVERFLOW)
    636 		return (rv);
    637 
    638 	buf.Pointer = AcpiOsAllocate(buf.Length);
    639 	if (buf.Pointer == NULL)
    640 		return (AE_NO_MEMORY);
    641 
    642 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    643 	param = (ACPI_OBJECT *)buf.Pointer;
    644 	if (rv == AE_OK) {
    645 		if (param->Type == ACPI_TYPE_STRING) {
    646 			/* XXX may leak buf.Pointer!! */
    647 			*stringp = param->String.Pointer;
    648 			return (AE_OK);
    649 		}
    650 		rv = AE_TYPE;
    651 	}
    652 
    653 	AcpiOsFree(buf.Pointer);
    654 	return (rv);
    655 }
    656 #endif
    657 
    658 
    659 /*
    660  * acpi_eval_struct:
    661  *
    662  *	Evaluate a more complex structure.  Caller must free buf.Pointer.
    663  */
    664 ACPI_STATUS
    665 acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
    666 {
    667 	ACPI_STATUS rv;
    668 
    669 	if (handle == NULL)
    670 		handle = ACPI_ROOT_OBJECT;
    671 
    672 	bufp->Pointer = NULL;
    673 	bufp->Length = 0;
    674 
    675 	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
    676 	if (rv != AE_BUFFER_OVERFLOW)
    677 		return (rv);
    678 
    679 	bufp->Pointer = AcpiOsAllocate(bufp->Length);
    680 	if (bufp->Pointer == NULL)
    681 		return (AE_NO_MEMORY);
    682 
    683 	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
    684 
    685 	return (rv);
    686 }
    687 
    688 /*
    689  * acpi_get:
    690  *
    691  *	Fetch data info the specified (empty) ACPI buffer.
    692  */
    693 ACPI_STATUS
    694 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
    695     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
    696 {
    697 	ACPI_STATUS rv;
    698 
    699 	buf->Pointer = NULL;
    700 	buf->Length = 0;
    701 
    702 	rv = (*getit)(handle, buf);
    703 	if (rv != AE_BUFFER_OVERFLOW)
    704 		return (rv);
    705 
    706 	buf->Pointer = AcpiOsCallocate(buf->Length);
    707 	if (buf->Pointer == NULL)
    708 		return (AE_NO_MEMORY);
    709 
    710 	return ((*getit)(handle, buf));
    711 }
    712