Home | History | Annotate | Line # | Download | only in acpi
acpi.c revision 1.6
      1 /*	$NetBSD: acpi.c,v 1.6 2002/01/12 16:43:53 tsutsui 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.6 2002/01/12 16:43:53 tsutsui 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 	char *str;
    482 
    483 	if (pnp) {
    484 		printf("%s ", aa->aa_node->ad_devinfo.HardwareId);
    485 		if (acpi_eval_string(aa->aa_node->ad_handle,
    486 		    "_STR", &str) == AE_OK) {
    487 			printf("[%s] ", str);
    488 			AcpiOsFree(str);
    489 		}
    490 		printf("at %s", pnp);
    491 	}
    492 
    493 	return (UNCONF);
    494 }
    495 
    496 /*****************************************************************************
    497  * ACPI fixed-hardware feature handlers
    498  *****************************************************************************/
    499 
    500 UINT32		acpi_fixed_power_button_handler(void *);
    501 UINT32		acpi_fixed_sleep_button_handler(void *);
    502 
    503 /*
    504  * acpi_enable_fixed_events:
    505  *
    506  *	Enable any fixed-hardware feature handlers.
    507  */
    508 void
    509 acpi_enable_fixed_events(struct acpi_softc *sc)
    510 {
    511 	static int beenhere;
    512 	ACPI_STATUS rv;
    513 
    514 	/*
    515 	 * Check for fixed-hardware buttons.
    516 	 */
    517 
    518 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
    519 		if (beenhere == 0)
    520 			printf("%s: fixed-feature power button present\n",
    521 			    sc->sc_dev.dv_xname);
    522 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
    523 		    acpi_fixed_power_button_handler, sc);
    524 		if (rv != AE_OK)
    525 			printf("%s: unable to install handler for fixed "
    526 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    527 	}
    528 
    529 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
    530 		if (beenhere == 0)
    531 			printf("%s: fixed-feature sleep button present\n",
    532 			    sc->sc_dev.dv_xname);
    533 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
    534 		    acpi_fixed_sleep_button_handler, sc);
    535 		if (rv != AE_OK)
    536 			printf("%s: unable to install handler for fixed "
    537 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    538 	}
    539 
    540 	beenhere = 1;
    541 }
    542 
    543 /*
    544  * acpi_fixed_power_button_handler:
    545  *
    546  *	Fixed event handler for the power button.
    547  */
    548 UINT32
    549 acpi_fixed_power_button_handler(void *context)
    550 {
    551 	struct acpi_softc *sc = context;
    552 
    553 	/* XXX XXX XXX */
    554 
    555 	printf("%s: fixed power button pressed\n", sc->sc_dev.dv_xname);
    556 
    557 	return (INTERRUPT_HANDLED);
    558 }
    559 
    560 /*
    561  * acpi_fixed_sleep_button_handler:
    562  *
    563  *	Fixed event handler for the sleep button.
    564  */
    565 UINT32
    566 acpi_fixed_sleep_button_handler(void *context)
    567 {
    568 	struct acpi_softc *sc = context;
    569 
    570 	/* XXX XXX XXX */
    571 
    572 	printf("%s: fixed sleep button pressed\n", sc->sc_dev.dv_xname);
    573 
    574 	return (INTERRUPT_HANDLED);
    575 }
    576 
    577 /*****************************************************************************
    578  * ACPI utility routines.
    579  *****************************************************************************/
    580 
    581 /*
    582  * acpi_eval_integer:
    583  *
    584  *	Evaluate an integer object.
    585  */
    586 ACPI_STATUS
    587 acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
    588 {
    589 	ACPI_STATUS rv;
    590 	ACPI_BUFFER buf;
    591 	ACPI_OBJECT param;
    592 
    593 	if (handle == NULL)
    594 		handle = ACPI_ROOT_OBJECT;
    595 
    596 	buf.Pointer = &param;
    597 	buf.Length = sizeof(param);
    598 
    599 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    600 	if (rv == AE_OK) {
    601 		if (param.Type == ACPI_TYPE_INTEGER)
    602 			*valp = param.Integer.Value;
    603 		else
    604 			rv = AE_TYPE;
    605 	}
    606 
    607 	return (rv);
    608 }
    609 
    610 /*
    611  * acpi_eval_string:
    612  *
    613  *	Evaluage a (Unicode) string object.
    614  */
    615 ACPI_STATUS
    616 acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
    617 {
    618 	ACPI_STATUS rv;
    619 	ACPI_BUFFER buf;
    620 	ACPI_OBJECT param;
    621 
    622 	if (handle == NULL)
    623 		handle = ACPI_ROOT_OBJECT;
    624 
    625 	buf.Pointer = NULL;
    626 	buf.Length = 0;
    627 
    628 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    629 	if (rv != AE_BUFFER_OVERFLOW)
    630 		return (rv);
    631 
    632 	buf.Pointer = AcpiOsAllocate(buf.Length);
    633 	if (buf.Pointer == NULL)
    634 		return (AE_NO_MEMORY);
    635 
    636 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    637 	if (rv == AE_OK) {
    638 		if (param.Type == ACPI_TYPE_STRING) {
    639 			*stringp = buf.Pointer;
    640 			return (AE_OK);
    641 		}
    642 		rv = AE_TYPE;
    643 	}
    644 
    645 	AcpiOsFree(buf.Pointer);
    646 	return (rv);
    647 }
    648 
    649 /*
    650  * acpi_get:
    651  *
    652  *	Fetch data info the specified (empty) ACPI buffer.
    653  */
    654 ACPI_STATUS
    655 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
    656     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
    657 {
    658 	ACPI_STATUS rv;
    659 
    660 	buf->Pointer = NULL;
    661 	buf->Length = 0;
    662 
    663 	rv = (*getit)(handle, buf);
    664 	if (rv != AE_BUFFER_OVERFLOW)
    665 		return (rv);
    666 
    667 	buf->Pointer = AcpiOsCallocate(buf->Length);
    668 	if (buf->Pointer == NULL)
    669 		return (AE_NO_MEMORY);
    670 
    671 	return ((*getit)(handle, buf));
    672 }
    673