Delete old acpi sources

git-svn-id: svn://kolibrios.org@9502 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
turbocat
2021-12-27 18:54:05 +00:00
parent 5abd6d0212
commit 3ad8304629
201 changed files with 0 additions and 98846 deletions

View File

@@ -1,192 +0,0 @@
CC = kos32-gcc
FASM = fasm.exe
DRV_DIR = $(CURDIR)/..
DRV_INCLUDES = $(DRV_DIR)/include
ACPI_INCLUDES = ./acpica/include
INCLUDES = -I$(DRV_INCLUDES) \
-I$(DRV_INCLUDES)/asm \
-I$(DRV_INCLUDES)/uapi
INCLUDES+= -I$(ACPI_INCLUDES) -I./
DEFINES = -D_LINUX -D__KERNEL__ -DCONFIG_X86 -DCONFIG_X86_32 -DCONFIG_PCI -DCONFIG_ACPI -DBUILDING_ACPICA
DEFINES += -DCONFIG_X86_CMPXCHG64 -DCONFIG_TINY_RCU -DCONFIG_X86_L1_CACHE_SHIFT=6
DEFINES += -DACPI_USE_LOCAL_CACHE -DACPI_NO_ERROR_MESSAGES
DEFINES += -DCONFIG_DMI -DCONFIG_ACPI_REDUCED_HARDWARE_ONLY -DKBUILD_MODNAME=\"acpi.dll\"
CFLAGS_OPT = -Os -march=i686 -fomit-frame-pointer -fno-ident -mno-stack-arg-probe
CFLAGS_OPT+= -fno-builtin-printf -fno-builtin-snprintf -fno-builtin-sscanf -fno-builtin-vsscanf
CFLAGS_OPT+= -fno-builtin-scnprintf -fno-builtin-vsprintf -fno-builtin-vsnprintf
CFLAGS_OPT+= -mno-ms-bitfields
CFLAGS = $(INCLUDES) $(DEFINES) $(CFLAGS_OPT)
PE_FLAGS=--major-os-version,0,--minor-os-version,7,--major-subsystem-version,0,--minor-subsystem-version,5,--subsystem,native
LDFLAGS=-e,_drvEntry,-nostdlib,-s,-pie,$(PE_FLAGS),--image-base,0,--file-alignment,512,--section-alignment,512
LIBPATH:= -L$(DRV_DIR)/ddk -L./acpica
LIBS:= -lcore
NAME= acpi
NAME_SRCS= acpi.c \
blacklist.c \
boot.c \
bus.c \
tables.c \
acpica/dsargs.c \
acpica/dscontrol.c \
acpica/dsdebug.c \
acpica/dsfield.c \
acpica/dsinit.c \
acpica/dsmethod.c \
acpica/dsmthdat.c \
acpica/dsobject.c \
acpica/dsopcode.c \
acpica/dsutils.c \
acpica/dswexec.c \
acpica/dswload.c \
acpica/dswload2.c \
acpica/dswscope.c \
acpica/dswstate.c \
acpica/evmisc.c \
acpica/evregion.c \
acpica/evrgnini.c \
acpica/exconfig.c \
acpica/exconvrt.c \
acpica/excreate.c \
acpica/exdebug.c \
acpica/exfield.c \
acpica/exfldio.c \
acpica/exmisc.c \
acpica/exmutex.c \
acpica/exnames.c \
acpica/exoparg1.c \
acpica/exoparg2.c \
acpica/exoparg3.c \
acpica/exoparg6.c \
acpica/exprep.c \
acpica/exresnte.c \
acpica/exresolv.c \
acpica/exresop.c \
acpica/exstore.c \
acpica/exstoren.c \
acpica/exstorob.c \
acpica/exsystem.c \
acpica/exutils.c \
acpica/nsaccess.c \
acpica/nsalloc.c \
acpica/nsarguments.c \
acpica/nsconvert.c \
acpica/nseval.c \
acpica/nsinit.c \
acpica/nsload.c \
acpica/nsnames.c \
acpica/nsobject.c \
acpica/nsparse.c \
acpica/nspredef.c \
acpica/nsprepkg.c \
acpica/nsrepair.c \
acpica/nsrepair2.c \
acpica/nssearch.c \
acpica/nsutils.c \
acpica/nswalk.c \
acpica/psargs.c \
acpica/psloop.c \
acpica/psobject.c \
acpica/psopcode.c \
acpica/psopinfo.c \
acpica/psparse.c \
acpica/psscope.c \
acpica/pstree.c \
acpica/psutils.c \
acpica/pswalk.c \
acpica/psxface.c \
acpica/tbdata.c \
acpica/tbfind.c \
acpica/tbfadt.c \
acpica/tbinstal.c \
acpica/tbprint.c \
acpica/tbutils.c \
acpica/tbxface.c \
acpica/tbxfload.c \
acpica/utaddress.c \
acpica/utalloc.c \
acpica/utbuffer.c \
acpica/utcache.c \
acpica/utcopy.c \
acpica/utdecode.c \
acpica/utdelete.c \
acpica/uterror.c \
acpica/utexcep.c \
acpica/utglobal.c \
acpica/uthex.c \
acpica/utinit.c \
acpica/utlock.c \
acpica/utmath.c \
acpica/utmisc.c \
acpica/utmutex.c \
acpica/utnonansi.c \
acpica/utobject.c \
acpica/utosi.c \
acpica/utownerid.c \
acpica/utpredef.c \
acpica/utresrc.c \
acpica/utstate.c \
acpica/utstring.c \
acpica/utxface.c \
acpica/utxferror.c \
acpica/utxfinit.c \
../ddk/debug/dbglog.c \
../ddk/io/create.c \
../ddk/io/finfo.c \
../ddk/io/ssize.c \
../ddk/io/write.c \
../ddk/malloc/malloc.c \
../ddk/linux/ctype.c \
../ddk/linux/div64.c \
../ddk/linux/dmi.c \
../ddk/linux/hexdump.c \
../ddk/stdio/vsprintf.c \
../ddk/string/strstr.c \
../ddk/string/_strncat.S\
../ddk/string/_strncmp.S\
../ddk/string/_strncpy.S\
../ddk/string/_strnlen.S\
../ddk/string/memcmp.S \
../ddk/string/strcat.S \
../ddk/string/strcmp.S \
../ddk/string/strcpy.S \
../ddk/string/strncmp.S \
../ddk/string/strncpy.S \
../ddk/string/strnlen.S \
$(NULL)
all: $(NAME).dll
NAME_OBJS = $(patsubst %.S, %.o, $(patsubst %.asm, %.o,\
$(patsubst %.c, %.o, $(NAME_SRCS))))
all: $(NAME).dll
$(NAME).dll: $(NAME_SRCS) acpi.lds Makefile
$(CC) $(CFLAGS) -nostdlib -fwhole-program -flto -Wl,-Map,acpi.map,-T,acpi.lds,$(LDFLAGS) -Wl,$(LIBPATH) -o $@ $(NAME_SRCS) $(LIBS)
strip $(NAME).dll
# kpack $(NAME).dll
%.o : %.S $(HFILES) Makefile
as -o $@ $<

Binary file not shown.

View File

@@ -1,27 +0,0 @@
use32
db 'MENUET01'
dd 1
dd start
dd i_end
dd mem
dd mem
dd 0
dd 0
start:
mov eax, 68
mov ebx, 21
mov ecx, sz_acpi
int 0x40
mov eax, -1
int 0x40
sz_acpi db '/rd/1/drivers/acpi.dll',0
align 4
i_end:
rb 128
mem:

View File

@@ -1,631 +0,0 @@
#include <syscall.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#define PREFIX "ACPI: "
int sbf_port __initdata = -1;
static bool acpi_os_initialized;
u32 __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
{
int result;
if(action != 1)
return 0;
if( !dbg_open("/tmp0/1/acpi.log") )
{
printk("Can't open /tmp0/1/acpi.log\nExit\n");
return 0;
}
dmi_scan_machine();
acpi_boot_table_init();
early_acpi_boot_init();
acpi_noirq_set();
acpi_early_init();
// if (acpi_disabled) {
// printk(KERN_INFO PREFIX "Interpreter disabled.\n");
// return -ENODEV;
// }
// init_acpi_device_notify();
// result = acpi_bus_init();
// if (result) {
// disable_acpi();
// return result;
// }
// pci_mmcfg_late_init();
// acpi_scan_init();
// acpi_ec_init();
// acpi_debugfs_init();
// acpi_sleep_proc_init();
// acpi_wakeup_device_init();
dbgprintf("module loaded\n");
return 0;
};
#define PREFIX "ACPI: "
u32 IMPORT AcpiGetRootPtr(void)__asm__("AcpiGetRootPtr");
acpi_physical_address __init acpi_os_get_root_pointer(void)
{
return AcpiGetRootPtr();
}
void* acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
return (void *)MapIoMem((addr_t)phys, size, PG_SW);
}
void acpi_os_unmap_memory(void *virt, acpi_size size)
{
u32 ptr = (u32)virt;
ptr &= 0xFFFFF000;
return FreeKernelSpace((void*)ptr);
}
void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
acpi_os_unmap_memory(virt, size);
}
int acpi_os_map_generic_address(struct acpi_generic_address *gas)
{
addr_t addr;
void *virt;
if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return 0;
addr = (addr_t)gas->address;
if (!addr || !gas->bit_width)
return -EINVAL;
virt = (void *)MapIoMem(addr, gas->bit_width / 8, PG_SW);
if (!virt)
return -EIO;
return 0;
}
void acpi_os_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
acpi_os_vprintf(fmt, args);
va_end(args);
}
void acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
vsprintf(buffer, fmt, args);
#ifdef ENABLE_DEBUGGER
if (acpi_in_debugger) {
kdb_printf("%s", buffer);
} else {
printk("%s", buffer);
}
#else
printk("%s", buffer);
#endif
}
static void acpi_table_taint(struct acpi_table_header *table)
{
pr_warn(PREFIX
"Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
table->signature, table->oem_table_id);
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
}
acpi_status
acpi_os_table_override(struct acpi_table_header * existing_table,
struct acpi_table_header ** new_table)
{
if (!existing_table || !new_table)
return AE_BAD_PARAMETER;
*new_table = NULL;
#ifdef CONFIG_ACPI_CUSTOM_DSDT
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
*new_table = (struct acpi_table_header *)AmlCode;
#endif
if (*new_table != NULL)
acpi_table_taint(existing_table);
return AE_OK;
}
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
acpi_physical_address *address,
u32 *table_length)
{
#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
*table_length = 0;
*address = 0;
return AE_OK;
#else
int table_offset = 0;
struct acpi_table_header *table;
*table_length = 0;
*address = 0;
if (!acpi_tables_addr)
return AE_OK;
do {
if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
WARN_ON(1);
return AE_OK;
}
table = acpi_os_map_memory(acpi_tables_addr + table_offset,
ACPI_HEADER_SIZE);
if (table_offset + table->length > all_tables_size) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
WARN_ON(1);
return AE_OK;
}
table_offset += table->length;
if (memcmp(existing_table->signature, table->signature, 4)) {
acpi_os_unmap_memory(table,
ACPI_HEADER_SIZE);
continue;
}
/* Only override tables with matching oem id */
if (memcmp(table->oem_table_id, existing_table->oem_table_id,
ACPI_OEM_TABLE_ID_SIZE)) {
acpi_os_unmap_memory(table,
ACPI_HEADER_SIZE);
continue;
}
table_offset -= table->length;
*table_length = table->length;
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
*address = acpi_tables_addr + table_offset;
break;
} while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
if (*address != 0)
acpi_table_taint(existing_table);
return AE_OK;
#endif
}
static struct osi_linux {
unsigned int enable:1;
unsigned int dmi:1;
unsigned int cmdline:1;
unsigned int default_disabling:1;
} osi_linux = {0, 0, 0, 0};
#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
#define OSI_STRING_ENTRIES_MAX 16 /* arbitrary */
struct osi_setup_entry {
char string[OSI_STRING_LENGTH_MAX];
bool enable;
};
static struct osi_setup_entry
osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
{"Module Device", true},
{"Processor Device", true},
{"3.0 _SCP Extensions", true},
{"Processor Aggregator Device", true},
};
void __init acpi_osi_setup(char *str)
{
struct osi_setup_entry *osi;
bool enable = true;
int i;
if (!acpi_gbl_create_osi_method)
return;
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
return;
}
if (*str == '!') {
str++;
if (*str == '\0') {
osi_linux.default_disabling = 1;
return;
} else if (*str == '*') {
acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
osi->enable = false;
}
return;
}
enable = false;
}
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
if (!strcmp(osi->string, str)) {
osi->enable = enable;
break;
} else if (osi->string[0] == '\0') {
osi->enable = enable;
strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
break;
}
}
}
static void __init set_osi_linux(unsigned int enable)
{
if (osi_linux.enable != enable)
osi_linux.enable = enable;
if (osi_linux.enable)
acpi_osi_setup("Linux");
else
acpi_osi_setup("!Linux");
return;
}
void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
if (enable == -1)
return;
osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */
set_osi_linux(enable);
return;
}
acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
{
void *sem = (void*)handle;
if (!acpi_os_initialized)
return AE_OK;
if (!sem || (units < 1))
return AE_BAD_PARAMETER;
if (units > 1)
return AE_SUPPORT;
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
handle, units, timeout));
return AE_OK;
}
acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
{
void *sem = (void*)handle;
if (!acpi_os_initialized)
return AE_OK;
if (!sem || (units < 1))
return AE_BAD_PARAMETER;
if (units > 1)
return AE_SUPPORT;
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
units));
// up(sem);
return AE_OK;
}
acpi_status __init acpi_os_initialize(void)
{
// acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
// acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
// acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
// acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block);
if (acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) {
/*
* Use acpi_os_map_generic_address to pre-map the reset
* register if it's in system memory.
*/
int rv;
rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register);
pr_debug(PREFIX "%s: map reset_reg status %d\n", __func__, rv);
}
acpi_os_initialized = true;
return AE_OK;
}
acpi_status __init acpi_os_initialize1(void)
{
// kacpid_wq = alloc_workqueue("kacpid", 0, 1);
// kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
// kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
// BUG_ON(!kacpid_wq);
// BUG_ON(!kacpi_notify_wq);
// BUG_ON(!kacpi_hotplug_wq);
// acpi_install_interface_handler(acpi_osi_handler);
// acpi_osi_setup_late();
return AE_OK;
}
acpi_status acpi_os_delete_semaphore(acpi_handle handle)
{
// void *sem = (void*)handle;
// if (!sem)
// return AE_BAD_PARAMETER;
// kfree(sem);
// sem = NULL;
return AE_OK;
}
acpi_status acpi_os_create_semaphore(u32 max_units,
u32 initial_units, acpi_handle * out_handle)
{
*out_handle = (acpi_handle) 1;
return (AE_OK);
}
acpi_status
acpi_os_create_mutex(acpi_handle * handle)
{
struct mutex *mtx = NULL;
mtx = kzalloc(sizeof(struct mutex),0);
if (!mtx)
return AE_NO_MEMORY;
mutex_init(mtx);
*handle = (acpi_handle *) mtx;
return AE_OK;
}
void acpi_os_release_mutex(acpi_mutex handle)
{
struct mutex *mtx = (struct mutex*)handle;
if (!acpi_os_initialized)
return;
mutex_unlock(mtx);
}
acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout)
{
struct mutex *mtx = (struct mutex*)handle;
if (!acpi_os_initialized)
return AE_OK;
mutex_lock(mtx);
return AE_OK;
}
void acpi_os_delete_mutex(acpi_mutex handle)
{
struct mutex *mtx = (struct mutex*)handle;
kfree(mtx);
};
acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
{
acpi_cpu_flags flags;
spin_lock_irqsave(lockp, flags);
return flags;
}
void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
{
spin_unlock_irqrestore(lockp, flags);
}
acpi_status acpi_os_signal(u32 function, void *info)
{
switch (function) {
case ACPI_SIGNAL_FATAL:
printk(KERN_ERR PREFIX "Fatal opcode executed\n");
break;
case ACPI_SIGNAL_BREAKPOINT:
/*
* AML Breakpoint
* ACPI spec. says to treat it as a NOP unless
* you are debugging. So if/when we integrate
* AML debugger into the kernel debugger its
* hook will go here. But until then it is
* not useful to print anything on breakpoints.
*/
break;
default:
break;
}
return AE_OK;
}
void acpi_os_sleep(u64 ms)
{
msleep(ms);
}
void acpi_os_stall(u32 us)
{
while (us) {
u32 delay = 1000;
if (delay > us)
delay = us;
udelay(delay);
// touch_nmi_watchdog();
us -= delay;
}
}
void msleep(unsigned int msecs)
{
msecs /= 10;
if(!msecs) msecs = 1;
__asm__ __volatile__ (
"call *__imp__Delay"
::"b" (msecs));
__asm__ __volatile__ (
"":::"ebx");
};
acpi_status acpi_os_execute(acpi_execute_type type,
acpi_osd_exec_callback function, void *context)
{
return AE_OK;
}
u64 acpi_os_get_timer(void)
{
u64 time_ns = ktime_to_ns(ktime_get());
do_div(time_ns, 100);
return time_ns;
}
ktime_t ktime_get(void)
{
ktime_t t;
t.tv64 = GetClockNs();
return t;
}
void __delay(unsigned long loops)
{
asm volatile(
"test %0,%0\n"
"jz 3f\n"
"jmp 1f\n"
".align 16\n"
"1: jmp 2f\n"
".align 16\n"
"2: dec %0\n"
" jnz 2b\n"
"3: dec %0\n"
: /* we don't need output */
: "a" (loops)
);
}
inline void __const_udelay(unsigned long xloops)
{
int d0;
xloops *= 4;
asm("mull %%edx"
: "=d" (xloops), "=&a" (d0)
: "1" (xloops), ""
(loops_per_jiffy * (HZ/4)));
__delay(++xloops);
}
void __udelay(unsigned long usecs)
{
__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
}
#define acpi_rev_override false
#define ACPI_MAX_OVERRIDE_LEN 100
static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
acpi_status
acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
char **new_val)
{
if (!init_val || !new_val)
return AE_BAD_PARAMETER;
*new_val = NULL;
if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
acpi_os_name);
*new_val = acpi_os_name;
}
if (!memcmp(init_val->name, "_REV", 4) && acpi_rev_override) {
printk(KERN_INFO PREFIX "Overriding _REV return value to 5\n");
*new_val = (char *)5;
}
return AE_OK;
}

View File

@@ -1,69 +0,0 @@
OUTPUT_FORMAT(pei-i386)
ENTRY("_drvEntry")
SECTIONS
{
. = SIZEOF_HEADERS;
. = ALIGN(__section_alignment__);
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
{
*(.text)
*(SORT(.text$*))
*(.text.*)
. = ALIGN(16);
*(.rdata)
*(SORT(.rdata$*))
. = ALIGN(16);
*(.data)
*(.data2)
*(SORT(.data$*))
. = ALIGN(16);
*(.bss)
*(COMMON)
}
.idata ALIGN(__section_alignment__):
{
SORT(*)(.idata$2)
SORT(*)(.idata$3)
/* These zeroes mark the end of the import list. */
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
SORT(*)(.idata$4)
SORT(*)(.idata$5)
SORT(*)(.idata$6)
SORT(*)(.idata$7)
}
.reloc ALIGN(__section_alignment__) :
{
*(.reloc)
}
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
*(.edata)
*(.note.GNU-stack)
*(.comment)
*(.eh_frame)
*(.debug_abbrev)
*(.debug_info)
*(.debug_line)
*(.debug_frame)
*(.debug_loc)
*(.debug_pubnames)
*(.debug_aranges)
*(.debug_ranges)
}
}

View File

@@ -1,173 +0,0 @@
/******************************************************************************
*
* Module Name: acapps - common include for ACPI applications/tools
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _ACAPPS
#define _ACAPPS
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2015 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH "-64"
#elif ACPI_MACHINE_WIDTH == 32
#define ACPI_WIDTH "-32"
#else
#error unknown ACPI_MACHINE_WIDTH
#define ACPI_WIDTH "-??"
#endif
/* Macros for signons and file headers */
#define ACPI_COMMON_SIGNON(utility_name) \
"\n%s\n%s version %8.8X%s\n%s\n\n", \
ACPICA_NAME, \
utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, \
ACPICA_COPYRIGHT
#define ACPI_COMMON_HEADER(utility_name, prefix) \
"%s%s\n%s%s version %8.8X%s\n%s%s\n%s\n", \
prefix, ACPICA_NAME, \
prefix, utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, \
prefix, ACPICA_COPYRIGHT, \
prefix
/* Macros for usage messages */
#define ACPI_USAGE_HEADER(usage) \
acpi_os_printf ("Usage: %s\nOptions:\n", usage);
#define ACPI_USAGE_TEXT(description) \
acpi_os_printf (description);
#define ACPI_OPTION(name, description) \
acpi_os_printf (" %-18s%s\n", name, description);
#define FILE_SUFFIX_DISASSEMBLY "dsl"
#define FILE_SUFFIX_BINARY_TABLE ".dat" /* Needs the dot */
/*
* getopt
*/
int acpi_getopt(int argc, char **argv, char *opts);
int acpi_getopt_argument(int argc, char **argv);
extern int acpi_gbl_optind;
extern int acpi_gbl_opterr;
extern int acpi_gbl_sub_opt_char;
extern char *acpi_gbl_optarg;
/*
* cmfsize - Common get file size function
*/
u32 cm_get_file_size(ACPI_FILE file);
#ifndef ACPI_DUMP_APP
/*
* adisasm
*/
acpi_status
ad_aml_disassemble(u8 out_to_file,
char *filename, char *prefix, char **out_filename);
void ad_print_statistics(void);
acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length);
void ad_dump_tables(void);
acpi_status ad_get_local_tables(void);
acpi_status
ad_parse_table(struct acpi_table_header *table,
acpi_owner_id * owner_id, u8 load_table, u8 external);
acpi_status ad_display_tables(char *filename, struct acpi_table_header *table);
acpi_status ad_display_statistics(void);
/*
* adwalk
*/
void
acpi_dm_cross_reference_namespace(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root,
acpi_owner_id owner_id);
void acpi_dm_dump_tree(union acpi_parse_object *origin);
void acpi_dm_find_orphan_methods(union acpi_parse_object *origin);
void
acpi_dm_finish_namespace_load(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root,
acpi_owner_id owner_id);
void
acpi_dm_convert_resource_indexes(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root);
/*
* adfile
*/
acpi_status ad_initialize(void);
char *fl_generate_filename(char *input_filename, char *suffix);
acpi_status
fl_split_input_pathname(char *input_path,
char **out_directory_path, char **out_filename);
char *ad_generate_filename(char *prefix, char *table_id);
void
ad_write_table(struct acpi_table_header *table,
u32 length, char *table_name, char *oem_table_id);
#endif
#endif /* _ACAPPS */

View File

@@ -1,66 +0,0 @@
/******************************************************************************
*
* Name: accommon.h - Common include files for generation of ACPICA source
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACCOMMON_H__
#define __ACCOMMON_H__
/*
* Common set of includes for all ACPICA source files.
* We put them here because we don't want to duplicate them
* in the the source code again and again.
*
* Note: The order of these include files is important.
*/
#include <acpi/acconfig.h> /* Global configuration constants */
#include "acmacros.h" /* C macros */
#include "aclocal.h" /* Internal data types */
#include "acobject.h" /* ACPI internal object */
#include "acstruct.h" /* Common structures */
#include "acglobal.h" /* All global variables */
#include "achware.h" /* Hardware defines and interfaces */
#include "acutils.h" /* Utility interfaces */
#ifndef ACPI_USE_SYSTEM_CLIBRARY
#include "acclib.h" /* C library interfaces */
#endif /* !ACPI_USE_SYSTEM_CLIBRARY */
#endif /* __ACCOMMON_H__ */

View File

@@ -1,302 +0,0 @@
/******************************************************************************
*
* Name: acdebug.h - ACPI/AML debugger
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACDEBUG_H__
#define __ACDEBUG_H__
/* The debugger is used in conjunction with the disassembler most of time */
#ifdef ACPI_DISASSEMBLER
#include "acdisasm.h"
#endif
#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
struct acpi_db_command_info {
char *name; /* Command Name */
u8 min_args; /* Minimum arguments required */
};
struct acpi_db_command_help {
u8 line_count; /* Number of help lines */
char *invocation; /* Command Invocation */
char *description; /* Command Description */
};
struct acpi_db_argument_info {
char *name; /* Argument Name */
};
struct acpi_db_execute_walk {
u32 count;
u32 max_count;
};
#define PARAM_LIST(pl) pl
#define EX_NO_SINGLE_STEP 1
#define EX_SINGLE_STEP 2
/*
* dbxface - external debugger interfaces
*/
acpi_status
acpi_db_single_step(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, u32 op_type);
/*
* dbcmds - debug commands and output routines
*/
struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string);
void acpi_db_display_table_info(char *table_arg);
void acpi_db_display_template(char *buffer_arg);
void acpi_db_unload_acpi_table(char *name);
void acpi_db_send_notify(char *name, u32 value);
void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
acpi_status acpi_db_sleep(char *object_arg);
void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg);
void acpi_db_display_locks(void);
void acpi_db_display_resources(char *object_arg);
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
void acpi_db_display_handlers(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_db_generate_gpe(char *gpe_arg,
char *block_arg))
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
void acpi_db_execute_test(char *type_arg);
/*
* dbconvert - miscellaneous conversion routines
*/
acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object);
acpi_status
acpi_db_convert_to_object(acpi_object_type type,
char *string, union acpi_object *object);
u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info);
void acpi_db_dump_pld_buffer(union acpi_object *obj_desc);
/*
* dbmethod - control method commands
*/
void
acpi_db_set_method_breakpoint(char *location,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
acpi_status acpi_db_disassemble_method(char *name);
void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
void acpi_db_batch_execute(char *count_arg);
/*
* dbnames - namespace commands
*/
void acpi_db_set_scope(char *name);
void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
void acpi_db_dump_namespace_paths(void);
void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
acpi_status acpi_db_find_name_in_namespace(char *name_arg);
void acpi_db_check_predefined_names(void);
acpi_status
acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
void acpi_db_check_integrity(void);
void acpi_db_find_references(char *object_arg);
void acpi_db_get_bus_info(void);
/*
* dbdisply - debug display commands
*/
void acpi_db_display_method_info(union acpi_parse_object *op);
void acpi_db_decode_and_display_object(char *target, char *output_type);
void
acpi_db_display_result_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
acpi_status acpi_db_display_all_methods(char *display_count_arg);
void acpi_db_display_arguments(void);
void acpi_db_display_locals(void);
void acpi_db_display_results(void);
void acpi_db_display_calling_tree(void);
void acpi_db_display_object_type(char *object_arg);
void
acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
/*
* dbexec - debugger control method execution
*/
void
acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags);
void
acpi_db_create_execution_threads(char *num_threads_arg,
char *num_loops_arg, char *method_name_arg);
void acpi_db_delete_objects(u32 count, union acpi_object *objects);
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
u32 acpi_db_get_cache_info(struct acpi_memory_list *cache);
#endif
/*
* dbfileio - Debugger file I/O commands
*/
acpi_object_type
acpi_db_match_argument(char *user_argument,
struct acpi_db_argument_info *arguments);
void acpi_db_close_debug_file(void);
void acpi_db_open_debug_file(char *name);
acpi_status acpi_db_load_acpi_table(char *filename);
acpi_status
acpi_db_get_table_from_file(char *filename,
struct acpi_table_header **table,
u8 must_be_aml_table);
/*
* dbhistry - debugger HISTORY command
*/
void acpi_db_add_to_history(char *command_line);
void acpi_db_display_history(void);
char *acpi_db_get_from_history(char *command_num_arg);
char *acpi_db_get_history_by_index(u32 commandd_num);
/*
* dbinput - user front-end to the AML debugger
*/
acpi_status
acpi_db_command_dispatch(char *input_buffer,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
char *acpi_db_get_next_token(char *string,
char **next, acpi_object_type * return_type);
/*
* dbobject
*/
void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc);
void
acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void acpi_db_decode_arguments(struct acpi_walk_state *walk_state);
void acpi_db_decode_locals(struct acpi_walk_state *walk_state);
void
acpi_db_dump_method_info(acpi_status status,
struct acpi_walk_state *walk_state);
/*
* dbstats - Generation and display of ACPI table statistics
*/
void acpi_db_generate_statistics(union acpi_parse_object *root, u8 is_method);
acpi_status acpi_db_display_statistics(char *type_arg);
/*
* dbutils - AML debugger utilities
*/
void acpi_db_set_output_destination(u32 where);
void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level);
void acpi_db_prep_namestring(char *name);
struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name);
void acpi_db_uint32_to_hex_string(u32 value, char *buffer);
#endif /* __ACDEBUG_H__ */

View File

@@ -1,365 +0,0 @@
/******************************************************************************
*
* Name: acdispat.h - dispatcher (parser to interpreter interface)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _ACDISPAT_H_
#define _ACDISPAT_H_
#define NAMEOF_LOCAL_NTE "__L0"
#define NAMEOF_ARG_NTE "__A0"
/*
* dsargs - execution of dynamic arguments for static objects
*/
acpi_status
acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc);
acpi_status
acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc);
acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *rgn_desc);
acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc);
acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc);
/*
* dscontrol - support for execution control opcodes
*/
acpi_status
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
/*
* dsopcode - support for late operand evaluation
*/
acpi_status
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
union acpi_operand_object *obj_desc);
acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);
/*
* dsexec - Parser/Interpreter interface, method execution callbacks
*/
acpi_status
acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
union acpi_operand_object *result_obj);
acpi_status
acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *state);
/*
* dsfield - Parser/Interpreter interface for AML fields
*/
acpi_status
acpi_ds_create_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_create_bank_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_create_index_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_create_buffer_field(union acpi_parse_object *op,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_init_field_objects(union acpi_parse_object *op,
struct acpi_walk_state *walk_state);
/*
* dsload - Parser/Interpreter interface
*/
acpi_status
acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
/* dsload - pass 1 namespace load callbacks */
acpi_status
acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
/* dsload - pass 2 namespace load callbacks */
acpi_status
acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state);
/*
* dsmthdat - method data (locals/args)
*/
acpi_status
acpi_ds_store_object_to_local(u8 type,
u32 index,
union acpi_operand_object *src_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_method_data_get_entry(u16 opcode,
u32 index,
struct acpi_walk_state *walk_state,
union acpi_operand_object ***node);
void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state);
u8 acpi_ds_is_method_value(union acpi_operand_object *obj_desc);
acpi_status
acpi_ds_method_data_get_value(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
union acpi_operand_object **dest_desc);
acpi_status
acpi_ds_method_data_init_args(union acpi_operand_object **params,
u32 max_param_count,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_method_data_get_node(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node);
void acpi_ds_method_data_init(struct acpi_walk_state *walk_state);
/*
* dsmethod - Parser/Interpreter interface - control method parsing
*/
acpi_status
acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
union acpi_operand_object *obj_desc);
acpi_status
acpi_ds_call_control_method(struct acpi_thread_state *thread,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
union acpi_operand_object *return_desc);
void
acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state);
/*
* dsinit
*/
acpi_status
acpi_ds_initialize_objects(u32 table_index,
struct acpi_namespace_node *start_node);
/*
* dsobject - Parser/Interpreter interface - object initialization and conversion
*/
acpi_status
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u32 buffer_length,
union acpi_operand_object **obj_desc_ptr);
acpi_status
acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u32 package_length,
union acpi_operand_object **obj_desc);
acpi_status
acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u16 opcode, union acpi_operand_object **obj_desc);
acpi_status
acpi_ds_create_node(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node,
union acpi_parse_object *op);
/*
* dsutils - Parser/Interpreter interface utility routines
*/
void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state);
u8
acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
struct acpi_walk_state *walk_state,
u8 add_reference);
u8
acpi_ds_is_result_used(union acpi_parse_object *op,
struct acpi_walk_state *walk_state);
void
acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
union acpi_operand_object *result_obj,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_create_operand(struct acpi_walk_state *walk_state,
union acpi_parse_object *arg, u32 args_remaining);
acpi_status
acpi_ds_create_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *first_arg);
acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state);
void acpi_ds_clear_operands(struct acpi_walk_state *walk_state);
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state);
/*
* dswscope - Scope Stack manipulation
*/
acpi_status
acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
acpi_object_type type,
struct acpi_walk_state *walk_state);
acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state);
void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state);
/*
* dswstate - parser WALK_STATE management routines
*/
acpi_status
acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id,
union acpi_parse_object
*origin,
union acpi_operand_object
*mth_desc,
struct acpi_thread_state
*thread);
acpi_status
acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
struct acpi_namespace_node *method_node,
u8 * aml_start,
u32 aml_length,
struct acpi_evaluate_info *info, u8 pass_number);
void
acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
struct acpi_walk_state *walk_state);
void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state);
struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state
*thread);
void
acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
struct acpi_thread_state *thread);
acpi_status acpi_ds_result_stack_clear(struct acpi_walk_state *walk_state);
struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
*thread);
acpi_status
acpi_ds_result_pop(union acpi_operand_object **object,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_result_push(union acpi_operand_object *object,
struct acpi_walk_state *walk_state);
/*
* dsdebug - parser debugging routines
*/
void
acpi_ds_dump_method_stack(acpi_status status,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
#endif /* _ACDISPAT_H_ */

View File

@@ -1,253 +0,0 @@
/******************************************************************************
*
* Name: acevents.h - Event subcomponent prototypes and defines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACEVENTS_H__
#define __ACEVENTS_H__
/*
* evevent
*/
acpi_status acpi_ev_initialize_events(void);
acpi_status acpi_ev_install_xrupt_handlers(void);
u32 acpi_ev_fixed_event_detect(void);
/*
* evmisc
*/
u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node);
u32 acpi_ev_get_gpe_number_index(u32 gpe_number);
acpi_status
acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
u32 notify_value);
/*
* evglock - Global Lock support
*/
acpi_status acpi_ev_init_global_lock_handler(void);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
acpi_ev_acquire_global_lock(u16 timeout))
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
acpi_status acpi_ev_remove_global_lock_handler(void);
/*
* evgpe - Low-level GPE support
*/
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block);
acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
/*
* evgpeblk - Upper-level GPE block support
*/
acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
u64 address,
u8 space_id,
u32 register_count,
u16 gpe_block_base_number,
u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block);
acpi_status
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
acpi_ev_delete_gpe_block(struct acpi_gpe_block_info
*gpe_block))
u32
acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_event_info *gpe_event_info,
u32 gpe_number);
/*
* evgpeinit - GPE initialization and update
*/
acpi_status acpi_ev_gpe_initialize(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_ev_update_gpes(acpi_owner_id table_owner_id))
acpi_status
acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
/*
* evgpeutil - GPE utilities
*/
acpi_status
acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context);
acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context);
acpi_status
acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
struct acpi_gpe_xrupt_info **gpe_xrupt_block);
acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
/*
* evhandler - Address space handling
*/
u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
acpi_adr_space_type space_id);
acpi_status acpi_ev_install_region_handlers(void);
acpi_status
acpi_ev_install_space_handler(struct acpi_namespace_node *node,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler,
acpi_adr_space_setup setup, void *context);
/*
* evregion - Operation region support
*/
acpi_status acpi_ev_initialize_op_regions(void);
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *field_obj,
u32 function,
u32 region_offset, u32 bit_width, u64 *value);
acpi_status
acpi_ev_attach_region(union acpi_operand_object *handler_obj,
union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked);
void
acpi_ev_detach_region(union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked);
acpi_status
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
acpi_adr_space_type space_id);
acpi_status
acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function);
/*
* evregini - Region initialization and setup
*/
acpi_status
acpi_ev_system_memory_region_setup(acpi_handle handle,
u32 function,
void *handler_context,
void **region_context);
acpi_status
acpi_ev_io_space_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
acpi_status
acpi_ev_pci_config_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
acpi_status
acpi_ev_cmos_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
acpi_status
acpi_ev_pci_bar_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
acpi_status
acpi_ev_default_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
acpi_status
acpi_ev_initialize_region(union acpi_operand_object *region_obj,
u8 acpi_ns_locked);
/*
* evsci - SCI (System Control Interrupt) handling/dispatch
*/
u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
u32 acpi_ev_sci_dispatch(void);
u32 acpi_ev_install_sci_handler(void);
acpi_status acpi_ev_remove_all_sci_handlers(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
#endif /* __ACEVENTS_H__ */

View File

@@ -1,395 +0,0 @@
/******************************************************************************
*
* Name: acglobal.h - Declarations for global variables
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACGLOBAL_H__
#define __ACGLOBAL_H__
/*****************************************************************************
*
* Globals related to the ACPI tables
*
****************************************************************************/
/* Master list of all ACPI tables that were found in the RSDT/XSDT */
ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list);
/* DSDT information. Used to check for DSDT corruption */
ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT);
ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header);
ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_fadt_index, ACPI_INVALID_TABLE_INDEX);
#if (!ACPI_REDUCED_HARDWARE)
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS);
#endif /* !ACPI_REDUCED_HARDWARE */
/* These addresses are calculated from the FADT Event Block addresses */
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_status);
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_enable);
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_status);
ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_enable);
/*
* Handle both ACPI 1.0 and ACPI 2.0+ Integer widths. The integer width is
* determined by the revision of the DSDT: If the DSDT revision is less than
* 2, use only the lower 32 bits of the internal 64-bit Integer.
*/
ACPI_GLOBAL(u8, acpi_gbl_integer_bit_width);
ACPI_GLOBAL(u8, acpi_gbl_integer_byte_width);
ACPI_GLOBAL(u8, acpi_gbl_integer_nybble_width);
/*****************************************************************************
*
* Mutual exclusion within ACPICA subsystem
*
****************************************************************************/
/*
* Predefined mutex objects. This array contains the
* actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs.
* (The table maps local handles to the real OS handles)
*/
ACPI_GLOBAL(struct acpi_mutex_info, acpi_gbl_mutex_info[ACPI_NUM_MUTEX]);
/*
* Global lock mutex is an actual AML mutex object
* Global lock semaphore works in conjunction with the actual global lock
* Global lock spinlock is used for "pending" handshake
*/
ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_global_lock_mutex);
ACPI_GLOBAL(acpi_semaphore, acpi_gbl_global_lock_semaphore);
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_global_lock_pending_lock);
ACPI_GLOBAL(u16, acpi_gbl_global_lock_handle);
ACPI_GLOBAL(u8, acpi_gbl_global_lock_acquired);
ACPI_GLOBAL(u8, acpi_gbl_global_lock_present);
ACPI_GLOBAL(u8, acpi_gbl_global_lock_pending);
/*
* Spinlocks are used for interfaces that can be possibly called at
* interrupt level
*/
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock);
/* Mutex for _OSI support */
ACPI_GLOBAL(acpi_mutex, acpi_gbl_osi_mutex);
/* Reader/Writer lock is used for namespace walk and dynamic table unload */
ACPI_GLOBAL(struct acpi_rw_lock, acpi_gbl_namespace_rw_lock);
/*****************************************************************************
*
* Miscellaneous globals
*
****************************************************************************/
/* Object caches */
ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_namespace_cache);
ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_state_cache);
ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_cache);
ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_ext_cache);
ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_operand_cache);
/* System */
ACPI_INIT_GLOBAL(u32, acpi_gbl_startup_flags, 0);
ACPI_INIT_GLOBAL(u8, acpi_gbl_shutdown, TRUE);
/* Global handlers */
ACPI_GLOBAL(struct acpi_global_notify_handler, acpi_gbl_global_notify[2]);
ACPI_GLOBAL(acpi_exception_handler, acpi_gbl_exception_handler);
ACPI_GLOBAL(acpi_init_handler, acpi_gbl_init_handler);
ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler);
ACPI_GLOBAL(void *, acpi_gbl_table_handler_context);
ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler);
ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list);
/* Owner ID support */
ACPI_GLOBAL(u32, acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]);
ACPI_GLOBAL(u8, acpi_gbl_last_owner_id_index);
ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset);
/* Initialization sequencing */
ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed);
/* Misc */
ACPI_GLOBAL(u32, acpi_gbl_original_mode);
ACPI_GLOBAL(u32, acpi_gbl_ns_lookup_count);
ACPI_GLOBAL(u32, acpi_gbl_ps_find_count);
ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save);
ACPI_GLOBAL(u8, acpi_gbl_debugger_configuration);
ACPI_GLOBAL(u8, acpi_gbl_step_to_next_call);
ACPI_GLOBAL(u8, acpi_gbl_acpi_hardware_present);
ACPI_GLOBAL(u8, acpi_gbl_events_initialized);
ACPI_GLOBAL(struct acpi_interface_info *, acpi_gbl_supported_interfaces);
ACPI_GLOBAL(struct acpi_address_range *,
acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX]);
/* Other miscellaneous, declared and initialized in utglobal */
extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS];
extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
/* Lists for tracking memory allocations (debug only) */
ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_global_list);
ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_ns_node_list);
ACPI_GLOBAL(u8, acpi_gbl_display_final_mem_stats);
ACPI_GLOBAL(u8, acpi_gbl_disable_mem_tracking);
#endif
/*****************************************************************************
*
* Namespace globals
*
****************************************************************************/
#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
#define NUM_PREDEFINED_NAMES 10
#else
#define NUM_PREDEFINED_NAMES 9
#endif
ACPI_GLOBAL(struct acpi_namespace_node, acpi_gbl_root_node_struct);
ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_root_node);
ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_fadt_gpe_device);
ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_module_code_list);
extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES];
extern const struct acpi_predefined_names
acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES];
#ifdef ACPI_DEBUG_OUTPUT
ACPI_GLOBAL(u32, acpi_gbl_current_node_count);
ACPI_GLOBAL(u32, acpi_gbl_current_node_size);
ACPI_GLOBAL(u32, acpi_gbl_max_concurrent_node_count);
ACPI_GLOBAL(acpi_size *, acpi_gbl_entry_stack_pointer);
ACPI_GLOBAL(acpi_size *, acpi_gbl_lowest_stack_pointer);
ACPI_GLOBAL(u32, acpi_gbl_deepest_nesting);
ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0);
#endif
/*****************************************************************************
*
* Interpreter globals
*
****************************************************************************/
ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list);
/* Maximum number of While() loop iterations before forced abort */
ACPI_GLOBAL(u16, acpi_gbl_max_loop_iterations);
/* Control method single step flag */
ACPI_GLOBAL(u8, acpi_gbl_cm_single_step);
/*****************************************************************************
*
* Hardware globals
*
****************************************************************************/
extern struct acpi_bit_register_info
acpi_gbl_bit_register_info[ACPI_NUM_BITREG];
ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a);
ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b);
/*****************************************************************************
*
* Event and GPE globals
*
****************************************************************************/
#if (!ACPI_REDUCED_HARDWARE)
ACPI_GLOBAL(u8, acpi_gbl_all_gpes_initialized);
ACPI_GLOBAL(struct acpi_gpe_xrupt_info *, acpi_gbl_gpe_xrupt_list_head);
ACPI_GLOBAL(struct acpi_gpe_block_info *,
acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]);
ACPI_GLOBAL(acpi_gbl_event_handler, acpi_gbl_global_event_handler);
ACPI_GLOBAL(void *, acpi_gbl_global_event_handler_context);
ACPI_GLOBAL(struct acpi_fixed_event_handler,
acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]);
extern struct acpi_fixed_event_info
acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS];
#endif /* !ACPI_REDUCED_HARDWARE */
/*****************************************************************************
*
* Debug support
*
****************************************************************************/
/* Event counters */
ACPI_GLOBAL(u32, acpi_method_count);
ACPI_GLOBAL(u32, acpi_gpe_count);
ACPI_GLOBAL(u32, acpi_sci_count);
ACPI_GLOBAL(u32, acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]);
/* Support for dynamic control method tracing mechanism */
ACPI_GLOBAL(u32, acpi_gbl_original_dbg_level);
ACPI_GLOBAL(u32, acpi_gbl_original_dbg_layer);
/*****************************************************************************
*
* Debugger and Disassembler globals
*
****************************************************************************/
ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT);
#ifdef ACPI_DISASSEMBLER
/* Do not disassemble buffers to resource descriptors */
ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_disassembly, TRUE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_force_aml_disassembly, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_opt_verbose, TRUE);
ACPI_GLOBAL(u8, acpi_gbl_dm_opt_disasm);
ACPI_GLOBAL(u8, acpi_gbl_dm_opt_listing);
ACPI_GLOBAL(u8, acpi_gbl_num_external_methods);
ACPI_GLOBAL(u32, acpi_gbl_resolved_external_methods);
ACPI_GLOBAL(struct acpi_external_list *, acpi_gbl_external_list);
ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list);
#endif
#ifdef ACPI_DEBUGGER
ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
ACPI_INIT_GLOBAL(acpi_thread_id, acpi_gbl_db_thread_id, ACPI_INVALID_THREAD_ID);
ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_ini_methods);
ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_region_support);
ACPI_GLOBAL(u8, acpi_gbl_db_output_to_file);
ACPI_GLOBAL(char *, acpi_gbl_db_buffer);
ACPI_GLOBAL(char *, acpi_gbl_db_filename);
ACPI_GLOBAL(u32, acpi_gbl_db_debug_level);
ACPI_GLOBAL(u32, acpi_gbl_db_console_debug_level);
ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_db_scope_node);
ACPI_GLOBAL(u8, acpi_gbl_db_terminate_loop);
ACPI_GLOBAL(u8, acpi_gbl_db_threads_terminated);
ACPI_GLOBAL(char *, acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]);
ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]);
/* These buffers should all be the same size */
ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]);
/*
* Statistic globals
*/
ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TOTAL_TYPES]);
ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TOTAL_TYPES]);
ACPI_GLOBAL(u16, acpi_gbl_obj_type_count_misc);
ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
ACPI_GLOBAL(u32, acpi_gbl_num_objects);
ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_ready);
ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_complete);
#endif /* ACPI_DEBUGGER */
/*****************************************************************************
*
* Application globals
*
****************************************************************************/
#ifdef ACPI_APPLICATION
ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL);
/* Print buffer */
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */
ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]);
#endif /* ACPI_APPLICATION */
/*****************************************************************************
*
* Info/help support
*
****************************************************************************/
extern const struct ah_predefined_name asl_predefined_info[];
extern const struct ah_device_id asl_device_ids[];
#endif /* __ACGLOBAL_H__ */

View File

@@ -1,150 +0,0 @@
/******************************************************************************
*
* Name: achware.h -- hardware specific interfaces
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACHWARE_H__
#define __ACHWARE_H__
/* Values for the _SST predefined method */
#define ACPI_SST_INDICATOR_OFF 0
#define ACPI_SST_WORKING 1
#define ACPI_SST_WAKING 2
#define ACPI_SST_SLEEPING 3
#define ACPI_SST_SLEEP_CONTEXT 4
/*
* hwacpi - high level functions
*/
acpi_status acpi_hw_set_mode(u32 mode);
u32 acpi_hw_get_mode(void);
/*
* hwregs - ACPI Register I/O
*/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address);
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg);
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg);
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control);
acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value);
acpi_status acpi_hw_register_write(u32 register_id, u32 value);
acpi_status acpi_hw_clear_acpi_status(void);
/*
* hwsleep - sleep/wake support (Legacy sleep registers)
*/
acpi_status acpi_hw_legacy_sleep(u8 sleep_state);
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state);
acpi_status acpi_hw_legacy_wake(u8 sleep_state);
/*
* hwesleep - sleep/wake support (Extended FADT-V5 sleep registers)
*/
void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument);
acpi_status acpi_hw_extended_sleep(u8 sleep_state);
acpi_status acpi_hw_extended_wake_prep(u8 sleep_state);
acpi_status acpi_hw_extended_wake(u8 sleep_state);
/*
* hwvalid - Port I/O with validation
*/
acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width);
acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
/*
* hwgpe - GPE support
*/
u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action);
acpi_status
acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context);
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context);
acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
acpi_status acpi_hw_disable_all_gpes(void);
acpi_status acpi_hw_enable_all_runtime_gpes(void);
acpi_status acpi_hw_enable_all_wakeup_gpes(void);
acpi_status
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
/*
* hwpci - PCI configuration support
*/
acpi_status
acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
acpi_handle root_pci_device, acpi_handle pci_region);
#endif /* __ACHWARE_H__ */

View File

@@ -1,556 +0,0 @@
/******************************************************************************
*
* Name: acinterp.h - Interpreter subcomponent prototypes and defines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACINTERP_H__
#define __ACINTERP_H__
#define ACPI_WALK_OPERANDS (&(walk_state->operands [walk_state->num_operands -1]))
/* Macros for tables used for debug output */
#define ACPI_EXD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_operand_object,f)
#define ACPI_EXD_NSOFFSET(f) (u8) ACPI_OFFSET (struct acpi_namespace_node,f)
#define ACPI_EXD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_exdump_info))
/*
* If possible, pack the following structures to byte alignment, since we
* don't care about performance for debug output. Two cases where we cannot
* pack the structures:
*
* 1) Hardware does not support misaligned memory transfers
* 2) Compiler does not support pointers within packed structures
*/
#if (!defined(ACPI_MISALIGNMENT_NOT_SUPPORTED) && !defined(ACPI_PACKED_POINTERS_NOT_SUPPORTED))
#pragma pack(1)
#endif
typedef const struct acpi_exdump_info {
u8 opcode;
u8 offset;
char *name;
} acpi_exdump_info;
/* Values for the Opcode field above */
#define ACPI_EXD_INIT 0
#define ACPI_EXD_TYPE 1
#define ACPI_EXD_UINT8 2
#define ACPI_EXD_UINT16 3
#define ACPI_EXD_UINT32 4
#define ACPI_EXD_UINT64 5
#define ACPI_EXD_LITERAL 6
#define ACPI_EXD_POINTER 7
#define ACPI_EXD_ADDRESS 8
#define ACPI_EXD_STRING 9
#define ACPI_EXD_BUFFER 10
#define ACPI_EXD_PACKAGE 11
#define ACPI_EXD_FIELD 12
#define ACPI_EXD_REFERENCE 13
#define ACPI_EXD_LIST 14 /* Operand object list */
#define ACPI_EXD_HDLR_LIST 15 /* Address Handler list */
#define ACPI_EXD_RGN_LIST 16 /* Region list */
#define ACPI_EXD_NODE 17 /* Namespace Node */
/* restore default alignment */
#pragma pack()
/*
* exconvrt - object conversion
*/
acpi_status
acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc, u32 flags);
acpi_status
acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc);
acpi_status
acpi_ex_convert_to_string(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc, u32 type);
/* Types for ->String conversion */
#define ACPI_EXPLICIT_BYTE_COPY 0x00000000
#define ACPI_EXPLICIT_CONVERT_HEX 0x00000001
#define ACPI_IMPLICIT_CONVERT_HEX 0x00000002
#define ACPI_EXPLICIT_CONVERT_DECIMAL 0x00000003
acpi_status
acpi_ex_convert_to_target_type(acpi_object_type destination_type,
union acpi_operand_object *source_desc,
union acpi_operand_object **result_desc,
struct acpi_walk_state *walk_state);
/*
* exdebug - AML debug object
*/
void
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
u32 level, u32 index);
void
acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void
acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void
acpi_ex_start_trace_opcode(union acpi_parse_object *op,
struct acpi_walk_state *walk_state);
void
acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
struct acpi_walk_state *walk_state);
void
acpi_ex_trace_point(acpi_trace_event_type type,
u8 begin, u8 *aml, char *pathname);
/*
* exfield - ACPI AML (p-code) execution - field manipulation
*/
acpi_status
acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc,
u32 buffer_length, u32 * datum_count);
acpi_status
acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
u64 mask,
u64 field_value, u32 field_datum_byte_offset);
void
acpi_ex_get_buffer_datum(u64 *datum,
void *buffer,
u32 buffer_length,
u32 byte_granularity, u32 buffer_offset);
void
acpi_ex_set_buffer_datum(u64 merged_datum,
void *buffer,
u32 buffer_length,
u32 byte_granularity, u32 buffer_offset);
acpi_status
acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
union acpi_operand_object *obj_desc,
union acpi_operand_object **ret_buffer_desc);
acpi_status
acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc);
/*
* exfldio - low level field I/O
*/
acpi_status
acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
void *buffer, u32 buffer_length);
acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
void *buffer, u32 buffer_length);
acpi_status
acpi_ex_access_region(union acpi_operand_object *obj_desc,
u32 field_datum_byte_offset, u64 *value, u32 read_write);
/*
* exmisc - misc support routines
*/
acpi_status
acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
union acpi_operand_object **return_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_concat_template(union acpi_operand_object *obj_desc,
union acpi_operand_object *obj_desc2,
union acpi_operand_object **actual_return_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_do_concatenate(union acpi_operand_object *obj_desc,
union acpi_operand_object *obj_desc2,
union acpi_operand_object **actual_return_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_do_logical_numeric_op(u16 opcode,
u64 integer0, u64 integer1, u8 *logical_result);
acpi_status
acpi_ex_do_logical_op(u16 opcode,
union acpi_operand_object *operand0,
union acpi_operand_object *operand1, u8 *logical_result);
u64 acpi_ex_do_math_op(u16 opcode, u64 operand0, u64 operand1);
acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_create_region(u8 * aml_start,
u32 aml_length,
u8 region_space, struct acpi_walk_state *walk_state);
acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_create_method(u8 * aml_start,
u32 aml_length, struct acpi_walk_state *walk_state);
/*
* exconfig - dynamic table load/unload
*/
acpi_status
acpi_ex_load_op(union acpi_operand_object *obj_desc,
union acpi_operand_object *target,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
union acpi_operand_object **return_desc);
acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle);
/*
* exmutex - mutex support
*/
acpi_status
acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_acquire_mutex_object(u16 timeout,
union acpi_operand_object *obj_desc,
acpi_thread_id thread_id);
acpi_status
acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc);
void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
/*
* exprep - ACPI AML execution - prep utilities
*/
acpi_status
acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
u8 field_flags,
u8 field_attribute,
u32 field_bit_position, u32 field_bit_length);
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info);
/*
* exsystem - Interface to OS services
*/
acpi_status
acpi_ex_system_do_notify_op(union acpi_operand_object *value,
union acpi_operand_object *obj_desc);
acpi_status acpi_ex_system_do_sleep(u64 time);
acpi_status acpi_ex_system_do_stall(u32 time);
acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc);
acpi_status
acpi_ex_system_wait_event(union acpi_operand_object *time,
union acpi_operand_object *obj_desc);
acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc);
acpi_status
acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout);
acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout);
/*
* exoparg1 - ACPI AML execution, 1 operand
*/
acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state);
/*
* exoparg2 - ACPI AML execution, 2 operands
*/
acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state);
/*
* exoparg3 - ACPI AML execution, 3 operands
*/
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state);
acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state);
/*
* exoparg6 - ACPI AML execution, 6 operands
*/
acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state *walk_state);
/*
* exresolv - Object resolution and get value functions
*/
acpi_status
acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
union acpi_operand_object *operand,
acpi_object_type * return_type,
union acpi_operand_object **return_desc);
/*
* exresnte - resolve namespace node
*/
acpi_status
acpi_ex_resolve_node_to_value(struct acpi_namespace_node **stack_ptr,
struct acpi_walk_state *walk_state);
/*
* exresop - resolve operand to value
*/
acpi_status
acpi_ex_resolve_operands(u16 opcode,
union acpi_operand_object **stack_ptr,
struct acpi_walk_state *walk_state);
/*
* exdump - Interpreter debug output routines
*/
void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth);
void
acpi_ex_dump_operands(union acpi_operand_object **operands,
const char *opcode_name, u32 num_opcodes);
void
acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags);
void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags);
/*
* exnames - AML namestring support
*/
acpi_status
acpi_ex_get_name_string(acpi_object_type data_type,
u8 * in_aml_address,
char **out_name_string, u32 * out_name_length);
/*
* exstore - Object store support
*/
acpi_status
acpi_ex_store(union acpi_operand_object *val_desc,
union acpi_operand_object *dest_desc,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
struct acpi_namespace_node *node,
struct acpi_walk_state *walk_state,
u8 implicit_conversion);
#define ACPI_IMPLICIT_CONVERSION TRUE
#define ACPI_NO_IMPLICIT_CONVERSION FALSE
/*
* exstoren - resolve/store object
*/
acpi_status
acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
acpi_object_type target_type,
struct acpi_walk_state *walk_state);
acpi_status
acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
union acpi_operand_object *dest_desc,
union acpi_operand_object **new_desc,
struct acpi_walk_state *walk_state);
/*
* exstorob - store object - buffer/string
*/
acpi_status
acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
acpi_status
acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
/*
* excopy - object copy
*/
acpi_status
acpi_ex_copy_integer_to_index_field(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
acpi_status
acpi_ex_copy_integer_to_bank_field(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
acpi_status
acpi_ex_copy_data_to_named_field(union acpi_operand_object *source_desc,
struct acpi_namespace_node *node);
acpi_status
acpi_ex_copy_integer_to_buffer_field(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
/*
* exutils - interpreter/scanner utilities
*/
void acpi_ex_enter_interpreter(void);
void acpi_ex_exit_interpreter(void);
u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
void acpi_ex_acquire_global_lock(u32 rule);
void acpi_ex_release_global_lock(u32 rule);
void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id);
void acpi_ex_integer_to_string(char *dest, u64 value);
void acpi_ex_pci_cls_to_string(char *dest, u8 class_code[3]);
u8 acpi_is_valid_space_id(u8 space_id);
/*
* exregion - default op_region handlers
*/
acpi_status
acpi_ex_system_memory_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context,
void *region_context);
acpi_status
acpi_ex_system_io_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
acpi_status
acpi_ex_pci_config_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
acpi_status
acpi_ex_cmos_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
acpi_status
acpi_ex_pci_bar_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
acpi_status
acpi_ex_embedded_controller_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context,
void *region_context);
acpi_status
acpi_ex_sm_bus_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
acpi_status
acpi_ex_data_table_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context);
#endif /* __INTERP_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,428 +0,0 @@
/******************************************************************************
*
* Name: acmacros.h - C macros for the entire subsystem.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACMACROS_H__
#define __ACMACROS_H__
/*
* Extract data using a pointer. Any more than a byte and we
* get into potential aligment issues -- see the STORE macros below.
* Use with care.
*/
#define ACPI_CAST8(ptr) ACPI_CAST_PTR (u8, (ptr))
#define ACPI_CAST16(ptr) ACPI_CAST_PTR (u16, (ptr))
#define ACPI_CAST32(ptr) ACPI_CAST_PTR (u32, (ptr))
#define ACPI_CAST64(ptr) ACPI_CAST_PTR (u64, (ptr))
#define ACPI_GET8(ptr) (*ACPI_CAST8 (ptr))
#define ACPI_GET16(ptr) (*ACPI_CAST16 (ptr))
#define ACPI_GET32(ptr) (*ACPI_CAST32 (ptr))
#define ACPI_GET64(ptr) (*ACPI_CAST64 (ptr))
#define ACPI_SET8(ptr, val) (*ACPI_CAST8 (ptr) = (u8) (val))
#define ACPI_SET16(ptr, val) (*ACPI_CAST16 (ptr) = (u16) (val))
#define ACPI_SET32(ptr, val) (*ACPI_CAST32 (ptr) = (u32) (val))
#define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val))
/*
* printf() format helper. This macros is a workaround for the difficulties
* with emitting 64-bit integers and 64-bit pointers with the same code
* for both 32-bit and 64-bit hosts.
*/
#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i)
/*
* Macros for moving data around to/from buffers that are possibly unaligned.
* If the hardware supports the transfer of unaligned data, just do the store.
* Otherwise, we have to move one byte at a time.
*/
#ifdef ACPI_BIG_ENDIAN
/*
* Macros for big-endian machines
*/
/* These macros reverse the bytes during the move, converting little-endian to big endian */
/* Big Endian <== Little Endian */
/* Hi...Lo Lo...Hi */
/* 16-bit source, 16/32/64 destination */
#define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d))=0;\
((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
/* 32-bit source, 16/32/64 destination */
#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
((u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[2];\
((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
/* 64-bit source, 16/32/64 destination */
#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[7];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[6];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[5];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[4];\
(( u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
(( u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
#else
/*
* Macros for little-endian machines
*/
#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
/* The hardware supports unaligned transfers, just do the little-endian move */
/* 16-bit source, 16/32/64 destination */
#define ACPI_MOVE_16_TO_16(d, s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s)
#define ACPI_MOVE_16_TO_32(d, s) *(u32 *)(void *)(d) = *(u16 *)(void *)(s)
#define ACPI_MOVE_16_TO_64(d, s) *(u64 *)(void *)(d) = *(u16 *)(void *)(s)
/* 32-bit source, 16/32/64 destination */
#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d, s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s)
#define ACPI_MOVE_32_TO_64(d, s) *(u64 *)(void *)(d) = *(u32 *)(void *)(s)
/* 64-bit source, 16/32/64 destination */
#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d, s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s)
#else
/*
* The hardware does not support unaligned transfers. We must move the
* data one byte at a time. These macros work whether the source or
* the destination (or both) is/are unaligned. (Little-endian move)
*/
/* 16-bit source, 16/32/64 destination */
#define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];}
#define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);}
#define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s);}
/* 32-bit source, 16/32/64 destination */
#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];}
#define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d)) = 0; ACPI_MOVE_32_TO_32(d, s);}
/* 64-bit source, 16/32/64 destination */
#define ACPI_MOVE_64_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_64_TO_32(d, s) ACPI_MOVE_32_TO_32(d, s) /* Truncate to 32 */
#define ACPI_MOVE_64_TO_64(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\
(( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\
(( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\
(( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];\
(( u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[4];\
(( u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[5];\
(( u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[6];\
(( u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[7];}
#endif
#endif
/*
* Fast power-of-two math macros for non-optimized compilers
*/
#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2)))
#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2)))
#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1)))
#define ACPI_DIV_2(a) _ACPI_DIV(a, 1)
#define ACPI_MUL_2(a) _ACPI_MUL(a, 1)
#define ACPI_MOD_2(a) _ACPI_MOD(a, 2)
#define ACPI_DIV_4(a) _ACPI_DIV(a, 2)
#define ACPI_MUL_4(a) _ACPI_MUL(a, 2)
#define ACPI_MOD_4(a) _ACPI_MOD(a, 4)
#define ACPI_DIV_8(a) _ACPI_DIV(a, 3)
#define ACPI_MUL_8(a) _ACPI_MUL(a, 3)
#define ACPI_MOD_8(a) _ACPI_MOD(a, 8)
#define ACPI_DIV_16(a) _ACPI_DIV(a, 4)
#define ACPI_MUL_16(a) _ACPI_MUL(a, 4)
#define ACPI_MOD_16(a) _ACPI_MOD(a, 16)
#define ACPI_DIV_32(a) _ACPI_DIV(a, 5)
#define ACPI_MUL_32(a) _ACPI_MUL(a, 5)
#define ACPI_MOD_32(a) _ACPI_MOD(a, 32)
/* Test for ASCII character */
#define ACPI_IS_ASCII(c) ((c) < 0x80)
/* Signed integers */
#define ACPI_SIGN_POSITIVE 0
#define ACPI_SIGN_NEGATIVE 1
/*
* Rounding macros (Power of two boundaries only)
*/
#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \
(~(((acpi_size) boundary)-1)))
#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \
(((acpi_size) boundary)-1)) & \
(~(((acpi_size) boundary)-1)))
/* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */
#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a, 4)
#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a, 8)
#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a, sizeof(acpi_size))
#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a, 4)
#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a, 8)
#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a, sizeof(acpi_size))
#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7)
#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a))
#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10)
/* Generic (non-power-of-two) rounding */
#define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary))
#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1))
/*
* Bitmask creation
* Bit positions start at zero.
* MASK_BITS_ABOVE creates a mask starting AT the position and above
* MASK_BITS_BELOW creates a mask starting one bit BELOW the position
*/
#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_UINT64_MAX) << ((u32) (position))))
#define ACPI_MASK_BITS_BELOW(position) ((ACPI_UINT64_MAX) << ((u32) (position)))
/* Bitfields within ACPI registers */
#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) \
((val << pos) & mask)
#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) \
reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
#define ACPI_INSERT_BITS(target, mask, source) \
target = ((target & (~(mask))) | (source & mask))
/* Generic bitfield macros and masks */
#define ACPI_GET_BITS(source_ptr, position, mask) \
((*source_ptr >> position) & mask)
#define ACPI_SET_BITS(target_ptr, position, mask, value) \
(*target_ptr |= ((value & mask) << position))
#define ACPI_1BIT_MASK 0x00000001
#define ACPI_2BIT_MASK 0x00000003
#define ACPI_3BIT_MASK 0x00000007
#define ACPI_4BIT_MASK 0x0000000F
#define ACPI_5BIT_MASK 0x0000001F
#define ACPI_6BIT_MASK 0x0000003F
#define ACPI_7BIT_MASK 0x0000007F
#define ACPI_8BIT_MASK 0x000000FF
#define ACPI_16BIT_MASK 0x0000FFFF
#define ACPI_24BIT_MASK 0x00FFFFFF
/* Macros to extract flag bits from position zero */
#define ACPI_GET_1BIT_FLAG(value) ((value) & ACPI_1BIT_MASK)
#define ACPI_GET_2BIT_FLAG(value) ((value) & ACPI_2BIT_MASK)
#define ACPI_GET_3BIT_FLAG(value) ((value) & ACPI_3BIT_MASK)
#define ACPI_GET_4BIT_FLAG(value) ((value) & ACPI_4BIT_MASK)
/* Macros to extract flag bits from position one and above */
#define ACPI_EXTRACT_1BIT_FLAG(field, position) (ACPI_GET_1BIT_FLAG ((field) >> position))
#define ACPI_EXTRACT_2BIT_FLAG(field, position) (ACPI_GET_2BIT_FLAG ((field) >> position))
#define ACPI_EXTRACT_3BIT_FLAG(field, position) (ACPI_GET_3BIT_FLAG ((field) >> position))
#define ACPI_EXTRACT_4BIT_FLAG(field, position) (ACPI_GET_4BIT_FLAG ((field) >> position))
/* ACPI Pathname helpers */
#define ACPI_IS_ROOT_PREFIX(c) ((c) == (u8) 0x5C) /* Backslash */
#define ACPI_IS_PARENT_PREFIX(c) ((c) == (u8) 0x5E) /* Carat */
#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (u8) 0x2E) /* Period (dot) */
/*
* An object of type struct acpi_namespace_node can appear in some contexts
* where a pointer to an object of type union acpi_operand_object can also
* appear. This macro is used to distinguish them.
*
* The "DescriptorType" field is the second field in both structures.
*/
#define ACPI_GET_DESCRIPTOR_PTR(d) (((union acpi_descriptor *)(void *)(d))->common.common_pointer)
#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((union acpi_descriptor *)(void *)(d))->common.common_pointer = (p))
#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = (t))
/*
* Macros for the master AML opcode table
*/
#if defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
#define ACPI_OP(name, Pargs, Iargs, obj_type, class, type, flags) \
{name, (u32)(Pargs), (u32)(Iargs), (u32)(flags), obj_type, class, type}
#else
#define ACPI_OP(name, Pargs, Iargs, obj_type, class, type, flags) \
{(u32)(Pargs), (u32)(Iargs), (u32)(flags), obj_type, class, type}
#endif
#define ARG_TYPE_WIDTH 5
#define ARG_1(x) ((u32)(x))
#define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH))
#define ARG_3(x) ((u32)(x) << (2 * ARG_TYPE_WIDTH))
#define ARG_4(x) ((u32)(x) << (3 * ARG_TYPE_WIDTH))
#define ARG_5(x) ((u32)(x) << (4 * ARG_TYPE_WIDTH))
#define ARG_6(x) ((u32)(x) << (5 * ARG_TYPE_WIDTH))
#define ARGI_LIST1(a) (ARG_1(a))
#define ARGI_LIST2(a, b) (ARG_1(b)|ARG_2(a))
#define ARGI_LIST3(a, b, c) (ARG_1(c)|ARG_2(b)|ARG_3(a))
#define ARGI_LIST4(a, b, c, d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a))
#define ARGI_LIST5(a, b, c, d, e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a))
#define ARGI_LIST6(a, b, c, d, e, f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a))
#define ARGP_LIST1(a) (ARG_1(a))
#define ARGP_LIST2(a, b) (ARG_1(a)|ARG_2(b))
#define ARGP_LIST3(a, b, c) (ARG_1(a)|ARG_2(b)|ARG_3(c))
#define ARGP_LIST4(a, b, c, d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d))
#define ARGP_LIST5(a, b, c, d, e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e))
#define ARGP_LIST6(a, b, c, d, e, f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f))
#define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F))
#define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH))
/*
* Ascii error messages can be configured out
*/
#ifndef ACPI_NO_ERROR_MESSAGES
/*
* Error reporting. Callers module and line number are inserted by AE_INFO,
* the plist contains a set of parens to allow variable-length lists.
* These macros are used for both the debug and non-debug versions of the code.
*/
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e);
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist
#define ACPI_BIOS_ERROR_PREDEFINED(plist) acpi_ut_predefined_bios_error plist
#else
/* No error messages */
#define ACPI_ERROR_NAMESPACE(s, e)
#define ACPI_ERROR_METHOD(s, n, p, e)
#define ACPI_WARN_PREDEFINED(plist)
#define ACPI_INFO_PREDEFINED(plist)
#define ACPI_BIOS_ERROR_PREDEFINED(plist)
#endif /* ACPI_NO_ERROR_MESSAGES */
#if (!ACPI_REDUCED_HARDWARE)
#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr
#else
#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL
#endif
/*
* Some code only gets executed when the debugger is built in.
* Note that this is entirely independent of whether the
* DEBUG_PRINT stuff (set by ACPI_DEBUG_OUTPUT) is on, or not.
*/
#ifdef ACPI_DEBUGGER
#define ACPI_DEBUGGER_EXEC(a) a
#else
#define ACPI_DEBUGGER_EXEC(a)
#endif
/*
* Macros used for ACPICA utilities only
*/
/* Generate a UUID */
#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
(a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
(b) & 0xFF, ((b) >> 8) & 0xFF, \
(c) & 0xFF, ((c) >> 8) & 0xFF, \
(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
#endif /* ACMACROS_H */

View File

@@ -1,407 +0,0 @@
/******************************************************************************
*
* Name: acnamesp.h - Namespace subcomponent prototypes and defines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACNAMESP_H__
#define __ACNAMESP_H__
/* To search the entire name space, pass this as search_base */
#define ACPI_NS_ALL ((acpi_handle)0)
/*
* Elements of acpi_ns_properties are bit significant
* and should be one-to-one with values of acpi_object_type
*/
#define ACPI_NS_NORMAL 0
#define ACPI_NS_NEWSCOPE 1 /* a definition of this type opens a name scope */
#define ACPI_NS_LOCAL 2 /* suppress search of enclosing scopes */
/* Flags for acpi_ns_lookup, acpi_ns_search_and_enter */
#define ACPI_NS_NO_UPSEARCH 0
#define ACPI_NS_SEARCH_PARENT 0x01
#define ACPI_NS_DONT_OPEN_SCOPE 0x02
#define ACPI_NS_NO_PEER_SEARCH 0x04
#define ACPI_NS_ERROR_IF_FOUND 0x08
#define ACPI_NS_PREFIX_IS_SCOPE 0x10
#define ACPI_NS_EXTERNAL 0x20
#define ACPI_NS_TEMPORARY 0x40
#define ACPI_NS_OVERRIDE_IF_FOUND 0x80
/* Flags for acpi_ns_walk_namespace */
#define ACPI_NS_WALK_NO_UNLOCK 0
#define ACPI_NS_WALK_UNLOCK 0x01
#define ACPI_NS_WALK_TEMP_NODES 0x02
/* Object is not a package element */
#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX
/* Always emit warning message, not dependent on node flags */
#define ACPI_WARN_ALWAYS 0
/*
* nsinit - Namespace initialization
*/
acpi_status acpi_ns_initialize_objects(void);
acpi_status acpi_ns_initialize_devices(void);
/*
* nsload - Namespace loading
*/
acpi_status acpi_ns_load_namespace(void);
acpi_status
acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node);
/*
* nswalk - walk the namespace
*/
acpi_status
acpi_ns_walk_namespace(acpi_object_type type,
acpi_handle start_object,
u32 max_depth,
u32 flags,
acpi_walk_callback descending_callback,
acpi_walk_callback ascending_callback,
void *context, void **return_value);
struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
*parent,
struct acpi_namespace_node
*child);
struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
struct
acpi_namespace_node
*parent,
struct
acpi_namespace_node
*child);
/*
* nsparse - table parsing
*/
acpi_status
acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node);
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
u32 table_index,
struct acpi_namespace_node *start_node);
/*
* nsaccess - Top-level namespace access
*/
acpi_status acpi_ns_root_initialize(void);
acpi_status
acpi_ns_lookup(union acpi_generic_state *scope_info,
char *name,
acpi_object_type type,
acpi_interpreter_mode interpreter_mode,
u32 flags,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **ret_node);
/*
* nsalloc - Named object allocation/deallocation
*/
struct acpi_namespace_node *acpi_ns_create_node(u32 name);
void acpi_ns_delete_node(struct acpi_namespace_node *node);
void acpi_ns_remove_node(struct acpi_namespace_node *node);
void
acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle);
void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id);
void acpi_ns_detach_object(struct acpi_namespace_node *node);
void acpi_ns_delete_children(struct acpi_namespace_node *parent);
int acpi_ns_compare_names(char *name1, char *name2);
/*
* nsconvert - Dynamic object conversion routines
*/
acpi_status
acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
acpi_status
acpi_ns_convert_to_string(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
acpi_status
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
acpi_status
acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
acpi_status
acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
/*
* nsdump - Namespace dump/print utilities
*/
void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth);
void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level);
void
acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component);
void acpi_ns_print_pathname(u32 num_segments, char *pathname);
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
void
acpi_ns_dump_objects(acpi_object_type type,
u8 display_type,
u32 max_depth,
acpi_owner_id owner_id, acpi_handle start_handle);
void
acpi_ns_dump_object_paths(acpi_object_type type,
u8 display_type,
u32 max_depth,
acpi_owner_id owner_id, acpi_handle start_handle);
/*
* nseval - Namespace evaluation functions
*/
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
void acpi_ns_exec_module_code_list(void);
/*
* nsarguments - Argument count/type checking for predefined/reserved names
*/
void
acpi_ns_check_argument_count(char *pathname,
struct acpi_namespace_node *node,
u32 user_param_count,
const union acpi_predefined_info *info);
void
acpi_ns_check_acpi_compliance(char *pathname,
struct acpi_namespace_node *node,
const union acpi_predefined_info *predefined);
void acpi_ns_check_argument_types(struct acpi_evaluate_info *info);
/*
* nspredef - Return value checking for predefined/reserved names
*/
acpi_status
acpi_ns_check_return_value(struct acpi_namespace_node *node,
struct acpi_evaluate_info *info,
u32 user_param_count,
acpi_status return_status,
union acpi_operand_object **return_object);
acpi_status
acpi_ns_check_object_type(struct acpi_evaluate_info *info,
union acpi_operand_object **return_object_ptr,
u32 expected_btypes, u32 package_index);
/*
* nsprepkg - Validation of predefined name packages
*/
acpi_status
acpi_ns_check_package(struct acpi_evaluate_info *info,
union acpi_operand_object **return_object_ptr);
/*
* nsnames - Name and Scope manipulation
*/
u32 acpi_ns_opens_scope(acpi_object_type type);
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node);
u32
acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
char *full_path, u32 path_size, u8 no_trailing);
char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
u8 no_trailing);
char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
acpi_status
acpi_ns_handle_to_pathname(acpi_handle target_handle,
struct acpi_buffer *buffer, u8 no_trailing);
u8
acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for);
acpi_status
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
const char *external_pathname,
u32 flags, struct acpi_namespace_node **out_node);
acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node);
/*
* nsobject - Object management for namespace nodes
*/
acpi_status
acpi_ns_attach_object(struct acpi_namespace_node *node,
union acpi_operand_object *object, acpi_object_type type);
union acpi_operand_object *acpi_ns_get_attached_object(struct
acpi_namespace_node
*node);
union acpi_operand_object *acpi_ns_get_secondary_object(union
acpi_operand_object
*obj_desc);
acpi_status
acpi_ns_attach_data(struct acpi_namespace_node *node,
acpi_object_handler handler, void *data);
acpi_status
acpi_ns_detach_data(struct acpi_namespace_node *node,
acpi_object_handler handler);
acpi_status
acpi_ns_get_attached_data(struct acpi_namespace_node *node,
acpi_object_handler handler, void **data);
/*
* nsrepair - General return object repair for all
* predefined methods/objects
*/
acpi_status
acpi_ns_simple_repair(struct acpi_evaluate_info *info,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr);
acpi_status
acpi_ns_wrap_with_package(struct acpi_evaluate_info *info,
union acpi_operand_object *original_object,
union acpi_operand_object **obj_desc_ptr);
acpi_status
acpi_ns_repair_null_element(struct acpi_evaluate_info *info,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr);
void
acpi_ns_remove_null_elements(struct acpi_evaluate_info *info,
u8 package_type,
union acpi_operand_object *obj_desc);
/*
* nsrepair2 - Return object repair for specific
* predefined methods/objects
*/
acpi_status
acpi_ns_complex_repairs(struct acpi_evaluate_info *info,
struct acpi_namespace_node *node,
acpi_status validate_status,
union acpi_operand_object **return_object_ptr);
/*
* nssearch - Namespace searching and entry
*/
acpi_status
acpi_ns_search_and_enter(u32 entry_name,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node,
acpi_interpreter_mode interpreter_mode,
acpi_object_type type,
u32 flags, struct acpi_namespace_node **ret_node);
acpi_status
acpi_ns_search_one_scope(u32 entry_name,
struct acpi_namespace_node *node,
acpi_object_type type,
struct acpi_namespace_node **ret_node);
void
acpi_ns_install_node(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *parent_node,
struct acpi_namespace_node *node, acpi_object_type type);
/*
* nsutils - Utility functions
*/
acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node);
u32 acpi_ns_local(acpi_object_type type);
void
acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg);
acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info);
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info);
acpi_status
acpi_ns_internalize_name(const char *dotted_name, char **converted_name);
acpi_status
acpi_ns_externalize_name(u32 internal_name_length,
const char *internal_name,
u32 * converted_name_length, char **converted_name);
struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle);
void acpi_ns_terminate(void);
#endif /* __ACNAMESP_H__ */

View File

@@ -1,465 +0,0 @@
/******************************************************************************
*
* Name: acobject.h - Definition of union acpi_operand_object (Internal object only)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _ACOBJECT_H
#define _ACOBJECT_H
/* acpisrc:struct_defs -- for acpisrc conversion */
/*
* The union acpi_operand_object is used to pass AML operands from the dispatcher
* to the interpreter, and to keep track of the various handlers such as
* address space handlers and notify handlers. The object is a constant
* size in order to allow it to be cached and reused.
*
* Note: The object is optimized to be aligned and will not work if it is
* byte-packed.
*/
#if ACPI_MACHINE_WIDTH == 64
#pragma pack(8)
#else
#pragma pack(4)
#endif
/*******************************************************************************
*
* Common Descriptors
*
******************************************************************************/
/*
* Common area for all objects.
*
* descriptor_type is used to differentiate between internal descriptors, and
* must be in the same place across all descriptors
*
* Note: The descriptor_type and Type fields must appear in the identical
* position in both the struct acpi_namespace_node and union acpi_operand_object
* structures.
*/
#define ACPI_OBJECT_COMMON_HEADER \
union acpi_operand_object *next_object; /* Objects linked to parent NS node */\
u8 descriptor_type; /* To differentiate various internal objs */\
u8 type; /* acpi_object_type */\
u16 reference_count; /* For object deletion management */\
u8 flags;
/*
* Note: There are 3 bytes available here before the
* next natural alignment boundary (for both 32/64 cases)
*/
/* Values for Flag byte above */
#define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */
#define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */
#define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */
#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */
#define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */
#define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */
/******************************************************************************
*
* Basic data types
*
*****************************************************************************/
struct acpi_object_common {
ACPI_OBJECT_COMMON_HEADER};
struct acpi_object_integer {
ACPI_OBJECT_COMMON_HEADER u8 fill[3]; /* Prevent warning on some compilers */
u64 value;
};
/*
* Note: The String and Buffer object must be identical through the
* pointer and length elements. There is code that depends on this.
*
* Fields common to both Strings and Buffers
*/
#define ACPI_COMMON_BUFFER_INFO(_type) \
_type *pointer; \
u32 length;
struct acpi_object_string { /* Null terminated, ASCII characters only */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */
};
struct acpi_object_buffer {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8) /* Buffer in AML stream or allocated buffer */
u32 aml_length;
u8 *aml_start;
struct acpi_namespace_node *node; /* Link back to parent node */
};
struct acpi_object_package {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Link back to parent node */
union acpi_operand_object **elements; /* Array of pointers to acpi_objects */
u8 *aml_start;
u32 aml_length;
u32 count; /* # of elements in package */
};
/******************************************************************************
*
* Complex data types
*
*****************************************************************************/
struct acpi_object_event {
ACPI_OBJECT_COMMON_HEADER acpi_semaphore os_semaphore; /* Actual OS synchronization object */
};
struct acpi_object_mutex {
ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */
u16 acquisition_depth; /* Allow multiple Acquires, same thread */
acpi_mutex os_mutex; /* Actual OS synchronization object */
acpi_thread_id thread_id; /* Current owner of the mutex */
struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
union acpi_operand_object *prev; /* Link for list of acquired mutexes */
union acpi_operand_object *next; /* Link for list of acquired mutexes */
struct acpi_namespace_node *node; /* Containing namespace node */
u8 original_sync_level; /* Owner's original sync level (0-15) */
};
struct acpi_object_region {
ACPI_OBJECT_COMMON_HEADER u8 space_id;
struct acpi_namespace_node *node; /* Containing namespace node */
union acpi_operand_object *handler; /* Handler for region access */
union acpi_operand_object *next;
acpi_physical_address address;
u32 length;
};
struct acpi_object_method {
ACPI_OBJECT_COMMON_HEADER u8 info_flags;
u8 param_count;
u8 sync_level;
union acpi_operand_object *mutex;
union acpi_operand_object *node;
u8 *aml_start;
union {
acpi_internal_method implementation;
union acpi_operand_object *handler;
} dispatch;
u32 aml_length;
u8 thread_count;
acpi_owner_id owner_id;
};
/* Flags for info_flags field above */
#define ACPI_METHOD_MODULE_LEVEL 0x01 /* Method is actually module-level code */
#define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */
#define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */
#define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */
#define ACPI_METHOD_IGNORE_SYNC_LEVEL 0x10 /* Method was auto-serialized at table load time */
#define ACPI_METHOD_MODIFIED_NAMESPACE 0x20 /* Method modified the namespace */
/******************************************************************************
*
* Objects that can be notified. All share a common notify_info area.
*
*****************************************************************************/
/*
* Common fields for objects that support ASL notifications
*/
#define ACPI_COMMON_NOTIFY_INFO \
union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\
union acpi_operand_object *handler; /* Handler for Address space */
struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
struct acpi_object_device {
ACPI_OBJECT_COMMON_HEADER
ACPI_COMMON_NOTIFY_INFO struct acpi_gpe_block_info *gpe_block;
};
struct acpi_object_power_resource {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 system_level;
u32 resource_order;
};
struct acpi_object_processor {
ACPI_OBJECT_COMMON_HEADER
/* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */
u8 proc_id;
u8 length;
ACPI_COMMON_NOTIFY_INFO acpi_io_address address;
};
struct acpi_object_thermal_zone {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
/******************************************************************************
*
* Fields. All share a common header/info field.
*
*****************************************************************************/
/*
* Common bitfield for the field objects
* "Field Datum" -- a datum from the actual field object
* "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field
*/
#define ACPI_COMMON_FIELD_INFO \
u8 field_flags; /* Access, update, and lock bits */\
u8 attribute; /* From access_as keyword */\
u8 access_byte_width; /* Read/Write size in bytes */\
struct acpi_namespace_node *node; /* Link back to parent node */\
u32 bit_length; /* Length of field in bits */\
u32 base_byte_offset; /* Byte offset within containing object */\
u32 value; /* Value to store into the Bank or Index register */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
u8 access_length; /* For serial regions/fields */
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
};
struct acpi_object_region_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
union acpi_operand_object *region_obj; /* Containing op_region object */
u8 *resource_buffer; /* resource_template for serial regions/fields */
u16 pin_number_index; /* Index relative to previous Connection/Template */
};
struct acpi_object_bank_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */
union acpi_operand_object *bank_obj; /* bank_select Register object */
};
struct acpi_object_index_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO
/*
* No "RegionObj" pointer needed since the Index and Data registers
* are each field definitions unto themselves.
*/
union acpi_operand_object *index_obj; /* Index register */
union acpi_operand_object *data_obj; /* Data register */
};
/* The buffer_field is different in that it is part of a Buffer, not an op_region */
struct acpi_object_buffer_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *buffer_obj; /* Containing Buffer object */
};
/******************************************************************************
*
* Objects for handlers
*
*****************************************************************************/
struct acpi_object_notify_handler {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */
u32 handler_type; /* Type: Device/System/Both */
acpi_notify_handler handler; /* Handler address */
void *context;
union acpi_operand_object *next[2]; /* Device and System handler lists */
};
struct acpi_object_addr_handler {
ACPI_OBJECT_COMMON_HEADER u8 space_id;
u8 handler_flags;
acpi_adr_space_handler handler;
struct acpi_namespace_node *node; /* Parent device */
void *context;
acpi_adr_space_setup setup;
union acpi_operand_object *region_list; /* Regions using this handler */
union acpi_operand_object *next;
};
/* Flags for address handler (handler_flags) */
#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x01
/******************************************************************************
*
* Special internal objects
*
*****************************************************************************/
/*
* The Reference object is used for these opcodes:
* Arg[0-6], Local[0-7], index_op, name_op, ref_of_op, load_op, load_table_op, debug_op
* The Reference.Class differentiates these types.
*/
struct acpi_object_reference {
ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */
u8 target_type; /* Used for Index Op */
u8 reserved;
void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
struct acpi_namespace_node *node; /* ref_of or Namepath */
union acpi_operand_object **where; /* Target of Index */
u8 *index_pointer; /* Used for Buffers and Strings */
u32 value; /* Used for Local/Arg/Index/ddb_handle */
};
/* Values for Reference.Class above */
typedef enum {
ACPI_REFCLASS_LOCAL = 0, /* Method local */
ACPI_REFCLASS_ARG = 1, /* Method argument */
ACPI_REFCLASS_REFOF = 2, /* Result of ref_of() TBD: Split to Ref/Node and Ref/operand_obj? */
ACPI_REFCLASS_INDEX = 3, /* Result of Index() */
ACPI_REFCLASS_TABLE = 4, /* ddb_handle - Load(), load_table() */
ACPI_REFCLASS_NAME = 5, /* Reference to a named object */
ACPI_REFCLASS_DEBUG = 6, /* Debug object */
ACPI_REFCLASS_MAX = 6
} ACPI_REFERENCE_CLASSES;
/*
* Extra object is used as additional storage for types that
* have AML code in their declarations (term_args) that must be
* evaluated at run time.
*
* Currently: Region and field_unit types
*/
struct acpi_object_extra {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */
struct acpi_namespace_node *scope_node;
void *region_context; /* Region-specific data */
u8 *aml_start;
u32 aml_length;
};
/* Additional data that can be attached to namespace nodes */
struct acpi_object_data {
ACPI_OBJECT_COMMON_HEADER acpi_object_handler handler;
void *pointer;
};
/* Structure used when objects are cached for reuse */
struct acpi_object_cache_list {
ACPI_OBJECT_COMMON_HEADER union acpi_operand_object *next; /* Link for object cache and internal lists */
};
/******************************************************************************
*
* union acpi_operand_object descriptor - a giant union of all of the above
*
*****************************************************************************/
union acpi_operand_object {
struct acpi_object_common common;
struct acpi_object_integer integer;
struct acpi_object_string string;
struct acpi_object_buffer buffer;
struct acpi_object_package package;
struct acpi_object_event event;
struct acpi_object_method method;
struct acpi_object_mutex mutex;
struct acpi_object_region region;
struct acpi_object_notify_common common_notify;
struct acpi_object_device device;
struct acpi_object_power_resource power_resource;
struct acpi_object_processor processor;
struct acpi_object_thermal_zone thermal_zone;
struct acpi_object_field_common common_field;
struct acpi_object_region_field field;
struct acpi_object_buffer_field buffer_field;
struct acpi_object_bank_field bank_field;
struct acpi_object_index_field index_field;
struct acpi_object_notify_handler notify;
struct acpi_object_addr_handler address_space;
struct acpi_object_reference reference;
struct acpi_object_extra extra;
struct acpi_object_data data;
struct acpi_object_cache_list cache;
/*
* Add namespace node to union in order to simplify code that accepts both
* ACPI_OPERAND_OBJECTs and ACPI_NAMESPACE_NODEs. The structures share
* a common descriptor_type field in order to differentiate them.
*/
struct acpi_namespace_node node;
};
/******************************************************************************
*
* union acpi_descriptor - objects that share a common descriptor identifier
*
*****************************************************************************/
/* Object descriptor types */
#define ACPI_DESC_TYPE_CACHED 0x01 /* Used only when object is cached */
#define ACPI_DESC_TYPE_STATE 0x02
#define ACPI_DESC_TYPE_STATE_UPDATE 0x03
#define ACPI_DESC_TYPE_STATE_PACKAGE 0x04
#define ACPI_DESC_TYPE_STATE_CONTROL 0x05
#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x06
#define ACPI_DESC_TYPE_STATE_PSCOPE 0x07
#define ACPI_DESC_TYPE_STATE_WSCOPE 0x08
#define ACPI_DESC_TYPE_STATE_RESULT 0x09
#define ACPI_DESC_TYPE_STATE_NOTIFY 0x0A
#define ACPI_DESC_TYPE_STATE_THREAD 0x0B
#define ACPI_DESC_TYPE_WALK 0x0C
#define ACPI_DESC_TYPE_PARSER 0x0D
#define ACPI_DESC_TYPE_OPERAND 0x0E
#define ACPI_DESC_TYPE_NAMED 0x0F
#define ACPI_DESC_TYPE_MAX 0x0F
struct acpi_common_descriptor {
void *common_pointer;
u8 descriptor_type; /* To differentiate various internal objs */
};
union acpi_descriptor {
struct acpi_common_descriptor common;
union acpi_operand_object object;
struct acpi_namespace_node node;
union acpi_parse_object op;
};
#pragma pack()
#endif /* _ACOBJECT_H */

View File

@@ -1,329 +0,0 @@
/******************************************************************************
*
* Name: acopcode.h - AML opcode information for the AML parser and interpreter
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACOPCODE_H__
#define __ACOPCODE_H__
#define MAX_EXTENDED_OPCODE 0x88
#define NUM_EXTENDED_OPCODE (MAX_EXTENDED_OPCODE + 1)
#define MAX_INTERNAL_OPCODE
#define NUM_INTERNAL_OPCODE (MAX_INTERNAL_OPCODE + 1)
/* Used for non-assigned opcodes */
#define _UNK 0x6B
/*
* Reserved ASCII characters. Do not use any of these for
* internal opcodes, since they are used to differentiate
* name strings from AML opcodes
*/
#define _ASC 0x6C
#define _NAM 0x6C
#define _PFX 0x6D
/*
* All AML opcodes and the parse-time arguments for each. Used by the AML
* parser Each list is compressed into a 32-bit number and stored in the
* master opcode table (in psopcode.c).
*/
#define ARGP_ACCESSFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_ACQUIRE_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_WORDDATA)
#define ARGP_ADD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_ALIAS_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_NAME)
#define ARGP_ARG0 ARG_NONE
#define ARGP_ARG1 ARG_NONE
#define ARGP_ARG2 ARG_NONE
#define ARGP_ARG3 ARG_NONE
#define ARGP_ARG4 ARG_NONE
#define ARGP_ARG5 ARG_NONE
#define ARGP_ARG6 ARG_NONE
#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST)
#define ARGP_BIT_AND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BIT_NAND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BIT_NOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BIT_NOT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BIT_OR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BIT_XOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_BREAK_OP ARG_NONE
#define ARGP_BREAK_POINT_OP ARG_NONE
#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST)
#define ARGP_BYTE_OP ARGP_LIST1 (ARGP_BYTEDATA)
#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
#define ARGP_CONNECTFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONTINUE_OP ARG_NONE
#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME)
#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_DATA_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_DEBUG_OP ARG_NONE
#define ARGP_DECREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST)
#define ARGP_DIVIDE_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET, ARGP_TARGET)
#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA)
#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST)
#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME)
#define ARGP_EXTERNAL_OP ARGP_LIST3 (ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_BYTEDATA)
#define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG)
#define ARGP_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST)
#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_FROM_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
#define ARGP_INCREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST)
#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME)
#define ARGP_LOAD_TABLE_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LOCAL0 ARG_NONE
#define ARGP_LOCAL1 ARG_NONE
#define ARGP_LOCAL2 ARG_NONE
#define ARGP_LOCAL3 ARG_NONE
#define ARGP_LOCAL4 ARG_NONE
#define ARGP_LOCAL5 ARG_NONE
#define ARGP_LOCAL6 ARG_NONE
#define ARGP_LOCAL7 ARG_NONE
#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST)
#define ARGP_METHODCALL_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_MID_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_MOD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_MULTIPLY_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_MUTEX_OP ARGP_LIST2 (ARGP_NAME, ARGP_BYTEDATA)
#define ARGP_NAME_OP ARGP_LIST2 (ARGP_NAME, ARGP_DATAOBJ)
#define ARGP_NAMEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_NOOP_OP ARG_NONE
#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
#define ARGP_ONE_OP ARG_NONE
#define ARGP_ONES_OP ARG_NONE
#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST)
#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST)
#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST)
#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA)
#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_RESET_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_REVISION_OP ARG_NONE
#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST)
#define ARGP_SERIALFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_STATICSTRING_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_STORE_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SUPERNAME)
#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST)
#define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST)
#define ARGP_TIMER_OP ARG_NONE
#define ARGP_TO_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_UNLOAD_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_DATAOBJLIST)
#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA)
#define ARGP_ZERO_OP ARG_NONE
/*
* All AML opcodes and the runtime arguments for each. Used by the AML
* interpreter Each list is compressed into a 32-bit number and stored
* in the master opcode table (in psopcode.c).
*
* (Used by prep_operands procedure and the ASL Compiler)
*/
#define ARGI_ACCESSFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_INTEGER)
#define ARGI_ADD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_ALIAS_OP ARGI_INVALID_OPCODE
#define ARGI_ARG0 ARG_NONE
#define ARGI_ARG1 ARG_NONE
#define ARGI_ARG2 ARG_NONE
#define ARGI_ARG3 ARG_NONE
#define ARGI_ARG4 ARG_NONE
#define ARGI_ARG5 ARG_NONE
#define ARGI_ARG6 ARG_NONE
#define ARGI_BANK_FIELD_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_BREAK_OP ARG_NONE
#define ARGI_BREAK_POINT_OP ARG_NONE
#define ARGI_BUFFER_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_BYTE_OP ARGI_INVALID_OPCODE
#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE
#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
#define ARGI_CONNECTFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE
#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET)
#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_CREATE_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_CREATE_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_CREATE_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING)
#define ARGI_DEBUG_OP ARG_NONE
#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_TARGETREF)
#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING)
#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE
#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF)
#define ARGI_DWORD_OP ARGI_INVALID_OPCODE
#define ARGI_ELSE_OP ARGI_INVALID_OPCODE
#define ARGI_EVENT_OP ARGI_INVALID_OPCODE
#define ARGI_EXTERNAL_OP ARGI_LIST3 (ARGI_STRING, ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_FIELD_OP ARGI_INVALID_OPCODE
#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_IF_OP ARGI_INVALID_OPCODE
#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_TARGETREF)
#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE
#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE
#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE
#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE
#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION_OR_BUFFER,ARGI_TARGETREF)
#define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_ANYTYPE)
#define ARGI_LOCAL0 ARG_NONE
#define ARGI_LOCAL1 ARG_NONE
#define ARGI_LOCAL2 ARG_NONE
#define ARGI_LOCAL3 ARG_NONE
#define ARGI_LOCAL4 ARG_NONE
#define ARGI_LOCAL5 ARG_NONE
#define ARGI_LOCAL6 ARG_NONE
#define ARGI_LOCAL7 ARG_NONE
#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_COMPUTEDATA, ARGI_INTEGER,ARGI_COMPUTEDATA,ARGI_INTEGER)
#define ARGI_METHOD_OP ARGI_INVALID_OPCODE
#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE
#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFER_OR_STRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_MOD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE
#define ARGI_NAME_OP ARGI_INVALID_OPCODE
#define ARGI_NAMEDFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE
#define ARGI_NOOP_OP ARG_NONE
#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
#define ARGI_ONE_OP ARG_NONE
#define ARGI_ONES_OP ARG_NONE
#define ARGI_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE
#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE
#define ARGI_QWORD_OP ARGI_INVALID_OPCODE
#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_OBJECT_REF)
#define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX)
#define ARGI_RESERVEDFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT)
#define ARGI_RETURN_OP ARGI_INVALID_OPCODE
#define ARGI_REVISION_OP ARG_NONE
#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE
#define ARGI_SERIALFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT)
#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE
#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_STORE_TARGET)
#define ARGI_STRING_OP ARGI_INVALID_OPCODE
#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE
#define ARGI_TIMER_OP ARG_NONE
#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
#define ARGI_WHILE_OP ARGI_INVALID_OPCODE
#define ARGI_WORD_OP ARGI_INVALID_OPCODE
#define ARGI_ZERO_OP ARG_NONE
#endif /* __ACOPCODE_H__ */

View File

@@ -1,253 +0,0 @@
/******************************************************************************
*
* Module Name: acparser.h - AML Parser subcomponent prototypes and defines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACPARSER_H__
#define __ACPARSER_H__
#define OP_HAS_RETURN_VALUE 1
/* Variable number of arguments. This field must be 32 bits */
#define ACPI_VAR_ARGS ACPI_UINT32_MAX
#define ACPI_PARSE_DELETE_TREE 0x0001
#define ACPI_PARSE_NO_TREE_DELETE 0x0000
#define ACPI_PARSE_TREE_MASK 0x0001
#define ACPI_PARSE_LOAD_PASS1 0x0010
#define ACPI_PARSE_LOAD_PASS2 0x0020
#define ACPI_PARSE_EXECUTE 0x0030
#define ACPI_PARSE_MODE_MASK 0x0030
#define ACPI_PARSE_DEFERRED_OP 0x0100
#define ACPI_PARSE_DISASSEMBLE 0x0200
#define ACPI_PARSE_MODULE_LEVEL 0x0400
/******************************************************************************
*
* Parser interfaces
*
*****************************************************************************/
extern const u8 acpi_gbl_short_op_index[];
extern const u8 acpi_gbl_long_op_index[];
/*
* psxface - Parser external interfaces
*/
acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info);
/*
* psargs - Parse AML opcode arguments
*/
u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state);
char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state);
void
acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
u32 arg_type, union acpi_parse_object *arg);
acpi_status
acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
struct acpi_parse_state *parser_state,
union acpi_parse_object *arg, u8 method_call);
acpi_status
acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
struct acpi_parse_state *parser_state,
u32 arg_type, union acpi_parse_object **return_arg);
/*
* psfind
*/
union acpi_parse_object *acpi_ps_find_name(union acpi_parse_object *scope,
u32 name, u32 opcode);
union acpi_parse_object *acpi_ps_get_parent(union acpi_parse_object *op);
/*
* psobject - support for parse object processing
*/
acpi_status
acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
u8 *aml_op_start,
union acpi_parse_object *unnamed_op,
union acpi_parse_object **op);
acpi_status
acpi_ps_create_op(struct acpi_walk_state *walk_state,
u8 *aml_op_start, union acpi_parse_object **new_op);
acpi_status
acpi_ps_complete_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **op, acpi_status status);
acpi_status
acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status);
/*
* psopinfo - AML Opcode information
*/
const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
char *acpi_ps_get_opcode_name(u16 opcode);
u8 acpi_ps_get_argument_count(u32 op_type);
/*
* psparse - top level parsing routines
*/
acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state);
u32 acpi_ps_get_opcode_size(u32 opcode);
u16 acpi_ps_peek_opcode(struct acpi_parse_state *state);
acpi_status
acpi_ps_complete_this_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
acpi_status
acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
acpi_status callback_status);
/*
* psloop - main parse loop
*/
acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state);
/*
* psscope - Scope stack management routines
*/
acpi_status
acpi_ps_init_scope(struct acpi_parse_state *parser_state,
union acpi_parse_object *root);
union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
*state);
u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state);
void
acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
union acpi_parse_object **op, u32 *arg_list, u32 *arg_count);
acpi_status
acpi_ps_push_scope(struct acpi_parse_state *parser_state,
union acpi_parse_object *op,
u32 remaining_args, u32 arg_count);
void acpi_ps_cleanup_scope(struct acpi_parse_state *state);
/*
* pstree - parse tree manipulation routines
*/
void
acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg);
union acpi_parse_object *acpi_ps_find(union acpi_parse_object *scope,
char *path, u16 opcode, u32 create);
union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn);
union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
union acpi_parse_object *op);
/*
* pswalk - parse tree walk routines
*/
acpi_status
acpi_ps_walk_parsed_aml(union acpi_parse_object *start_op,
union acpi_parse_object *end_op,
union acpi_operand_object *mth_desc,
struct acpi_namespace_node *start_node,
union acpi_operand_object **params,
union acpi_operand_object **caller_return_desc,
acpi_owner_id owner_id,
acpi_parse_downwards descending_callback,
acpi_parse_upwards ascending_callback);
acpi_status
acpi_ps_get_next_walk_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
acpi_parse_upwards ascending_callback);
acpi_status acpi_ps_delete_completed_op(struct acpi_walk_state *walk_state);
void acpi_ps_delete_parse_tree(union acpi_parse_object *root);
/*
* psutils - parser utilities
*/
union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml);
void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode);
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml);
void acpi_ps_free_op(union acpi_parse_object *op);
u8 acpi_ps_is_leading_char(u32 c);
u32 acpi_ps_get_name(union acpi_parse_object *op);
void acpi_ps_set_name(union acpi_parse_object *op, u32 name);
/*
* psdump - display parser tree
*/
u32
acpi_ps_sprint_path(char *buffer_start,
u32 buffer_size, union acpi_parse_object *op);
u32
acpi_ps_sprint_op(char *buffer_start,
u32 buffer_size, union acpi_parse_object *op);
void acpi_ps_show(union acpi_parse_object *op);
#endif /* __ACPARSER_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,383 +0,0 @@
/******************************************************************************
*
* Name: acresrc.h - Resource Manager function prototypes
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACRESRC_H__
#define __ACRESRC_H__
/* Need the AML resource descriptor structs */
#include "amlresrc.h"
/*
* If possible, pack the following structures to byte alignment, since we
* don't care about performance for debug output. Two cases where we cannot
* pack the structures:
*
* 1) Hardware does not support misaligned memory transfers
* 2) Compiler does not support pointers within packed structures
*/
#if (!defined(ACPI_MISALIGNMENT_NOT_SUPPORTED) && !defined(ACPI_PACKED_POINTERS_NOT_SUPPORTED))
#pragma pack(1)
#endif
/*
* Individual entry for the resource conversion tables
*/
typedef const struct acpi_rsconvert_info {
u8 opcode;
u8 resource_offset;
u8 aml_offset;
u8 value;
} acpi_rsconvert_info;
/* Resource conversion opcodes */
typedef enum {
ACPI_RSC_INITGET = 0,
ACPI_RSC_INITSET,
ACPI_RSC_FLAGINIT,
ACPI_RSC_1BITFLAG,
ACPI_RSC_2BITFLAG,
ACPI_RSC_3BITFLAG,
ACPI_RSC_ADDRESS,
ACPI_RSC_BITMASK,
ACPI_RSC_BITMASK16,
ACPI_RSC_COUNT,
ACPI_RSC_COUNT16,
ACPI_RSC_COUNT_GPIO_PIN,
ACPI_RSC_COUNT_GPIO_RES,
ACPI_RSC_COUNT_GPIO_VEN,
ACPI_RSC_COUNT_SERIAL_RES,
ACPI_RSC_COUNT_SERIAL_VEN,
ACPI_RSC_DATA8,
ACPI_RSC_EXIT_EQ,
ACPI_RSC_EXIT_LE,
ACPI_RSC_EXIT_NE,
ACPI_RSC_LENGTH,
ACPI_RSC_MOVE_GPIO_PIN,
ACPI_RSC_MOVE_GPIO_RES,
ACPI_RSC_MOVE_SERIAL_RES,
ACPI_RSC_MOVE_SERIAL_VEN,
ACPI_RSC_MOVE8,
ACPI_RSC_MOVE16,
ACPI_RSC_MOVE32,
ACPI_RSC_MOVE64,
ACPI_RSC_SET8,
ACPI_RSC_SOURCE,
ACPI_RSC_SOURCEX
} ACPI_RSCONVERT_OPCODES;
/* Resource Conversion sub-opcodes */
#define ACPI_RSC_COMPARE_AML_LENGTH 0
#define ACPI_RSC_COMPARE_VALUE 1
#define ACPI_RSC_TABLE_SIZE(d) (sizeof (d) / sizeof (struct acpi_rsconvert_info))
#define ACPI_RS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_resource,f)
#define AML_OFFSET(f) (u8) ACPI_OFFSET (union aml_resource,f)
/*
* Individual entry for the resource dump tables
*/
typedef const struct acpi_rsdump_info {
u8 opcode;
u8 offset;
char *name;
const char **pointer;
} acpi_rsdump_info;
/* Values for the Opcode field above */
typedef enum {
ACPI_RSD_TITLE = 0,
ACPI_RSD_1BITFLAG,
ACPI_RSD_2BITFLAG,
ACPI_RSD_3BITFLAG,
ACPI_RSD_ADDRESS,
ACPI_RSD_DWORDLIST,
ACPI_RSD_LITERAL,
ACPI_RSD_LONGLIST,
ACPI_RSD_SHORTLIST,
ACPI_RSD_SHORTLISTX,
ACPI_RSD_SOURCE,
ACPI_RSD_STRING,
ACPI_RSD_UINT8,
ACPI_RSD_UINT16,
ACPI_RSD_UINT32,
ACPI_RSD_UINT64,
ACPI_RSD_WORDLIST
} ACPI_RSDUMP_OPCODES;
/* restore default alignment */
#pragma pack()
/* Resource tables indexed by internal resource type */
extern const u8 acpi_gbl_aml_resource_sizes[];
extern const u8 acpi_gbl_aml_resource_serial_bus_sizes[];
extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[];
/* Resource tables indexed by raw AML resource descriptor type */
extern const u8 acpi_gbl_resource_struct_sizes[];
extern const u8 acpi_gbl_resource_struct_serial_bus_sizes[];
extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[];
extern struct acpi_rsconvert_info
*acpi_gbl_convert_resource_serial_bus_dispatch[];
struct acpi_vendor_walk_info {
struct acpi_vendor_uuid *uuid;
struct acpi_buffer *buffer;
acpi_status status;
};
/*
* rscreate
*/
acpi_status
acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
struct acpi_buffer *output_buffer);
acpi_status
acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
struct acpi_buffer *output_buffer);
acpi_status
acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
struct acpi_buffer *output_buffer);
/*
* rsutils
*/
acpi_status
acpi_rs_get_prt_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_get_method_data(acpi_handle handle,
char *path, struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
/*
* rscalc
*/
acpi_status
acpi_rs_get_list_length(u8 * aml_buffer,
u32 aml_buffer_length, acpi_size * size_needed);
acpi_status
acpi_rs_get_aml_length(struct acpi_resource *resource_list,
acpi_size resource_list_size, acpi_size * size_needed);
acpi_status
acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
acpi_size * buffer_size_needed);
acpi_status
acpi_rs_convert_aml_to_resources(u8 * aml,
u32 length,
u32 offset, u8 resource_index, void **context);
acpi_status
acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
acpi_size aml_size_needed, u8 * output_buffer);
/*
* rsaddr
*/
void
acpi_rs_set_address_common(union aml_resource *aml,
struct acpi_resource *resource);
u8
acpi_rs_get_address_common(struct acpi_resource *resource,
union aml_resource *aml);
/*
* rsmisc
*/
acpi_status
acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
union aml_resource *aml,
struct acpi_rsconvert_info *info);
acpi_status
acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
union aml_resource *aml,
struct acpi_rsconvert_info *info);
/*
* rsutils
*/
void
acpi_rs_move_data(void *destination,
void *source, u16 item_count, u8 move_type);
u8 acpi_rs_decode_bitmask(u16 mask, u8 * list);
u16 acpi_rs_encode_bitmask(u8 * list, u8 count);
acpi_rs_length
acpi_rs_get_resource_source(acpi_rs_length resource_length,
acpi_rs_length minimum_length,
struct acpi_resource_source *resource_source,
union aml_resource *aml, char *string_ptr);
acpi_rsdesc_size
acpi_rs_set_resource_source(union aml_resource *aml,
acpi_rs_length minimum_length,
struct acpi_resource_source *resource_source);
void
acpi_rs_set_resource_header(u8 descriptor_type,
acpi_rsdesc_size total_length,
union aml_resource *aml);
void
acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
union aml_resource *aml);
/*
* rsdump - Debugger support
*/
#ifdef ACPI_DEBUGGER
void acpi_rs_dump_resource_list(struct acpi_resource *resource);
void acpi_rs_dump_irq_list(u8 *route_table);
#endif
/*
* Resource conversion tables
*/
extern struct acpi_rsconvert_info acpi_rs_convert_dma[];
extern struct acpi_rsconvert_info acpi_rs_convert_end_dpf[];
extern struct acpi_rsconvert_info acpi_rs_convert_io[];
extern struct acpi_rsconvert_info acpi_rs_convert_fixed_io[];
extern struct acpi_rsconvert_info acpi_rs_convert_end_tag[];
extern struct acpi_rsconvert_info acpi_rs_convert_memory24[];
extern struct acpi_rsconvert_info acpi_rs_convert_generic_reg[];
extern struct acpi_rsconvert_info acpi_rs_convert_memory32[];
extern struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[];
extern struct acpi_rsconvert_info acpi_rs_convert_address32[];
extern struct acpi_rsconvert_info acpi_rs_convert_address16[];
extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[];
extern struct acpi_rsconvert_info acpi_rs_convert_address64[];
extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[];
extern struct acpi_rsconvert_info acpi_rs_convert_gpio[];
extern struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[];
extern struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[];
extern struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[];
extern struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[];
/* These resources require separate get/set tables */
extern struct acpi_rsconvert_info acpi_rs_get_irq[];
extern struct acpi_rsconvert_info acpi_rs_get_start_dpf[];
extern struct acpi_rsconvert_info acpi_rs_get_vendor_small[];
extern struct acpi_rsconvert_info acpi_rs_get_vendor_large[];
extern struct acpi_rsconvert_info acpi_rs_set_irq[];
extern struct acpi_rsconvert_info acpi_rs_set_start_dpf[];
extern struct acpi_rsconvert_info acpi_rs_set_vendor[];
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*
* rsinfo
*/
extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[];
extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[];
/*
* rsdumpinfo
*/
extern struct acpi_rsdump_info acpi_rs_dump_irq[];
extern struct acpi_rsdump_info acpi_rs_dump_prt[];
extern struct acpi_rsdump_info acpi_rs_dump_dma[];
extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[];
extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[];
extern struct acpi_rsdump_info acpi_rs_dump_io[];
extern struct acpi_rsdump_info acpi_rs_dump_io_flags[];
extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[];
extern struct acpi_rsdump_info acpi_rs_dump_vendor[];
extern struct acpi_rsdump_info acpi_rs_dump_end_tag[];
extern struct acpi_rsdump_info acpi_rs_dump_memory24[];
extern struct acpi_rsdump_info acpi_rs_dump_memory32[];
extern struct acpi_rsdump_info acpi_rs_dump_memory_flags[];
extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[];
extern struct acpi_rsdump_info acpi_rs_dump_address16[];
extern struct acpi_rsdump_info acpi_rs_dump_address32[];
extern struct acpi_rsdump_info acpi_rs_dump_address64[];
extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[];
extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[];
extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[];
extern struct acpi_rsdump_info acpi_rs_dump_gpio[];
extern struct acpi_rsdump_info acpi_rs_dump_fixed_dma[];
extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[];
extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[];
extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[];
extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[];
extern struct acpi_rsdump_info acpi_rs_dump_general_flags[];
#endif
#endif /* __ACRESRC_H__ */

View File

@@ -1,243 +0,0 @@
/******************************************************************************
*
* Name: acstruct.h - Internal structs
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACSTRUCT_H__
#define __ACSTRUCT_H__
/* acpisrc:struct_defs -- for acpisrc conversion */
/*****************************************************************************
*
* Tree walking typedefs and structs
*
****************************************************************************/
/*
* Walk state - current state of a parse tree walk. Used for both a leisurely
* stroll through the tree (for whatever reason), and for control method
* execution.
*/
#define ACPI_NEXT_OP_DOWNWARD 1
#define ACPI_NEXT_OP_UPWARD 2
/*
* Groups of definitions for walk_type used for different implementations of
* walkers (never simultaneously) - flags for interpreter:
*/
#define ACPI_WALK_NON_METHOD 0
#define ACPI_WALK_METHOD 0x01
#define ACPI_WALK_METHOD_RESTART 0x02
struct acpi_walk_state {
struct acpi_walk_state *next; /* Next walk_state in list */
u8 descriptor_type; /* To differentiate various internal objs */
u8 walk_type;
u16 opcode; /* Current AML opcode */
u8 next_op_info; /* Info about next_op */
u8 num_operands; /* Stack pointer for Operands[] array */
u8 operand_index; /* Index into operand stack, to be used by acpi_ds_obj_stack_push */
acpi_owner_id owner_id; /* Owner of objects created during the walk */
u8 last_predicate; /* Result of last predicate */
u8 current_result;
u8 return_used;
u8 scope_depth;
u8 pass_number; /* Parse pass during table load */
u8 namespace_override; /* Override existing objects */
u8 result_size; /* Total elements for the result stack */
u8 result_count; /* Current number of occupied elements of result stack */
u8 *aml;
u32 arg_types;
u32 method_breakpoint; /* For single stepping */
u32 user_breakpoint; /* User AML breakpoint */
u32 parse_flags;
struct acpi_parse_state parser_state; /* Current state of parser */
u32 prev_arg_types;
u32 arg_count; /* push for fixed or var args */
struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */
union acpi_operand_object **params;
u8 *aml_last_while;
union acpi_operand_object **caller_return_desc;
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
union acpi_operand_object *implicit_return_obj;
struct acpi_namespace_node *method_call_node; /* Called method Node */
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
union acpi_operand_object *method_desc; /* Method descriptor if running a method */
struct acpi_namespace_node *method_node; /* Method node if running a method. */
union acpi_parse_object *op; /* Current parser op */
const struct acpi_opcode_info *op_info; /* Info on current opcode */
union acpi_parse_object *origin; /* Start of walk [Obsolete] */
union acpi_operand_object *result_obj;
union acpi_generic_state *results; /* Stack of accumulated results */
union acpi_operand_object *return_desc; /* Return object, if any */
union acpi_generic_state *scope_info; /* Stack of nested scopes */
union acpi_parse_object *prev_op; /* Last op that was processed */
union acpi_parse_object *next_op; /* next op to be processed */
struct acpi_thread_state *thread;
acpi_parse_downwards descending_callback;
acpi_parse_upwards ascending_callback;
};
/* Info used by acpi_ns_initialize_objects and acpi_ds_initialize_objects */
struct acpi_init_walk_info {
u32 table_index;
u32 object_count;
u32 method_count;
u32 serial_method_count;
u32 non_serial_method_count;
u32 serialized_method_count;
u32 device_count;
u32 op_region_count;
u32 field_count;
u32 buffer_count;
u32 package_count;
u32 op_region_init;
u32 field_init;
u32 buffer_init;
u32 package_init;
acpi_owner_id owner_id;
};
struct acpi_get_devices_info {
acpi_walk_callback user_function;
void *context;
const char *hid;
};
union acpi_aml_operands {
union acpi_operand_object *operands[7];
struct {
struct acpi_object_integer *type;
struct acpi_object_integer *code;
struct acpi_object_integer *argument;
} fatal;
struct {
union acpi_operand_object *source;
struct acpi_object_integer *index;
union acpi_operand_object *target;
} index;
struct {
union acpi_operand_object *source;
struct acpi_object_integer *index;
struct acpi_object_integer *length;
union acpi_operand_object *target;
} mid;
};
/*
* Structure used to pass object evaluation information and parameters.
* Purpose is to reduce CPU stack use.
*/
struct acpi_evaluate_info {
/* The first 3 elements are passed by the caller to acpi_ns_evaluate */
struct acpi_namespace_node *prefix_node; /* Input: starting node */
char *relative_pathname; /* Input: path relative to prefix_node */
union acpi_operand_object **parameters; /* Input: argument list */
struct acpi_namespace_node *node; /* Resolved node (prefix_node:relative_pathname) */
union acpi_operand_object *obj_desc; /* Object attached to the resolved node */
char *full_pathname; /* Full pathname of the resolved node */
const union acpi_predefined_info *predefined; /* Used if Node is a predefined name */
union acpi_operand_object *return_object; /* Object returned from the evaluation */
union acpi_operand_object *parent_package; /* Used if return object is a Package */
u32 return_flags; /* Used for return value analysis */
u32 return_btype; /* Bitmapped type of the returned object */
u16 param_count; /* Count of the input argument list */
u8 pass_number; /* Parser pass number */
u8 return_object_type; /* Object type of the returned object */
u8 node_flags; /* Same as Node->Flags */
u8 flags; /* General flags */
};
/* Values for Flags above */
#define ACPI_IGNORE_RETURN_VALUE 1
/* Defines for return_flags field above */
#define ACPI_OBJECT_REPAIRED 1
#define ACPI_OBJECT_WRAPPED 2
/* Info used by acpi_ns_initialize_devices */
struct acpi_device_walk_info {
struct acpi_table_desc *table_desc;
struct acpi_evaluate_info *evaluate_info;
u32 device_count;
u32 num_STA;
u32 num_INI;
};
/* TBD: [Restructure] Merge with struct above */
struct acpi_walk_info {
u32 debug_level;
u32 count;
acpi_owner_id owner_id;
u8 display_type;
};
/* Display Types */
#define ACPI_DISPLAY_SUMMARY (u8) 0
#define ACPI_DISPLAY_OBJECTS (u8) 1
#define ACPI_DISPLAY_MASK (u8) 1
#define ACPI_DISPLAY_SHORT (u8) 2
#endif

View File

@@ -1,171 +0,0 @@
/******************************************************************************
*
* Name: actables.h - ACPI table management
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __ACTABLES_H__
#define __ACTABLES_H__
acpi_status acpi_allocate_root_table(u32 initial_table_count);
/*
* tbxfroot - Root pointer utilities
*/
u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp);
acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
/*
* tbdata - table data structure management
*/
acpi_status
acpi_tb_get_next_table_descriptor(u32 *table_index,
struct acpi_table_desc **table_desc);
void
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
acpi_physical_address address,
u8 flags, struct acpi_table_header *table);
acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
acpi_physical_address address, u8 flags);
void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc);
acpi_status
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature);
u8 acpi_tb_is_table_loaded(u32 table_index);
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
/*
* tbfadt - FADT parse/convert/validate
*/
void acpi_tb_parse_fadt(void);
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
/*
* tbfind - find ACPI table
*/
acpi_status
acpi_tb_find_table(char *signature,
char *oem_id, char *oem_table_id, u32 *table_index);
/*
* tbinstal - Table removal and deletion
*/
acpi_status acpi_tb_resize_root_table_list(void);
acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc);
void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc);
void acpi_tb_override_table(struct acpi_table_desc *old_table_desc);
acpi_status
acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
struct acpi_table_header **table_ptr,
u32 *table_length, u8 *table_flags);
void
acpi_tb_release_table(struct acpi_table_header *table,
u32 table_length, u8 table_flags);
acpi_status
acpi_tb_install_standard_table(acpi_physical_address address,
u8 flags,
u8 reload, u8 override, u32 *table_index);
void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc);
void acpi_tb_terminate(void);
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);
acpi_status acpi_tb_allocate_owner_id(u32 table_index);
acpi_status acpi_tb_release_owner_id(u32 table_index);
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id);
/*
* tbutils - table manager utilities
*/
acpi_status acpi_tb_initialize_facs(void);
void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header);
u8 acpi_tb_checksum(u8 *buffer, u32 length);
acpi_status
acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
void acpi_tb_check_dsdt_header(void);
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
void
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
u8 override, u32 *table_index);
acpi_status
acpi_tb_install_fixed_table(acpi_physical_address address,
char *signature, u32 *table_index);
acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
u8 acpi_is_valid_signature(char *signature);
/*
* tbxfload
*/
acpi_status acpi_tb_load_namespace(void);
#endif /* __ACTABLES_H__ */

View File

@@ -1,733 +0,0 @@
/******************************************************************************
*
* Name: acutils.h -- prototypes for the common (subsystem-wide) procedures
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _ACUTILS_H
#define _ACUTILS_H
extern const u8 acpi_gbl_resource_aml_sizes[];
extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[];
/* Strings used by the disassembler and debugger resource dump routines */
#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
extern const char *acpi_gbl_bm_decode[];
extern const char *acpi_gbl_config_decode[];
extern const char *acpi_gbl_consume_decode[];
extern const char *acpi_gbl_dec_decode[];
extern const char *acpi_gbl_he_decode[];
extern const char *acpi_gbl_io_decode[];
extern const char *acpi_gbl_ll_decode[];
extern const char *acpi_gbl_max_decode[];
extern const char *acpi_gbl_mem_decode[];
extern const char *acpi_gbl_min_decode[];
extern const char *acpi_gbl_mtp_decode[];
extern const char *acpi_gbl_rng_decode[];
extern const char *acpi_gbl_rw_decode[];
extern const char *acpi_gbl_shr_decode[];
extern const char *acpi_gbl_siz_decode[];
extern const char *acpi_gbl_trs_decode[];
extern const char *acpi_gbl_ttp_decode[];
extern const char *acpi_gbl_typ_decode[];
extern const char *acpi_gbl_ppc_decode[];
extern const char *acpi_gbl_ior_decode[];
extern const char *acpi_gbl_dts_decode[];
extern const char *acpi_gbl_ct_decode[];
extern const char *acpi_gbl_sbt_decode[];
extern const char *acpi_gbl_am_decode[];
extern const char *acpi_gbl_sm_decode[];
extern const char *acpi_gbl_wm_decode[];
extern const char *acpi_gbl_cph_decode[];
extern const char *acpi_gbl_cpo_decode[];
extern const char *acpi_gbl_dp_decode[];
extern const char *acpi_gbl_ed_decode[];
extern const char *acpi_gbl_bpb_decode[];
extern const char *acpi_gbl_sb_decode[];
extern const char *acpi_gbl_fc_decode[];
extern const char *acpi_gbl_pt_decode[];
#endif
/*
* For the iASL compiler case, the output is redirected to stderr so that
* any of the various ACPI errors and warnings do not appear in the output
* files, for either the compiler or disassembler portions of the tool.
*/
#ifdef ACPI_ASL_COMPILER
#include <stdio.h>
#define ACPI_MSG_REDIRECT_BEGIN \
FILE *output_file = acpi_gbl_output_file; \
acpi_os_redirect_output (stderr);
#define ACPI_MSG_REDIRECT_END \
acpi_os_redirect_output (output_file);
#else
/*
* non-iASL case - no redirection, nothing to do
*/
#define ACPI_MSG_REDIRECT_BEGIN
#define ACPI_MSG_REDIRECT_END
#endif
/*
* Common error message prefixes
*/
#define ACPI_MSG_ERROR "ACPI Error: "
#define ACPI_MSG_EXCEPTION "ACPI Exception: "
#define ACPI_MSG_WARNING "ACPI Warning: "
#define ACPI_MSG_INFO "ACPI: "
#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): "
#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): "
/*
* Common message suffix
*/
#define ACPI_MSG_SUFFIX \
acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
/* Types for Resource descriptor entries */
#define ACPI_INVALID_RESOURCE 0
#define ACPI_FIXED_LENGTH 1
#define ACPI_VARIABLE_LENGTH 2
#define ACPI_SMALL_VARIABLE_LENGTH 3
typedef
acpi_status(*acpi_walk_aml_callback) (u8 *aml,
u32 length,
u32 offset,
u8 resource_index, void **context);
typedef
acpi_status(*acpi_pkg_callback) (u8 object_type,
union acpi_operand_object *source_object,
union acpi_generic_state * state,
void *context);
struct acpi_pkg_info {
u8 *free_space;
acpi_size length;
u32 object_space;
u32 num_packages;
};
/* Object reference counts */
#define REF_INCREMENT (u16) 0
#define REF_DECREMENT (u16) 1
/* acpi_ut_dump_buffer */
#define DB_BYTE_DISPLAY 1
#define DB_WORD_DISPLAY 2
#define DB_DWORD_DISPLAY 4
#define DB_QWORD_DISPLAY 8
/*
* utnonansi - Non-ANSI C library functions
*/
void acpi_ut_strupr(char *src_string);
void acpi_ut_strlwr(char *src_string);
int acpi_ut_stricmp(char *string1, char *string2);
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
/*
* utglobal - Global data structures and procedures
*/
acpi_status acpi_ut_init_globals(void);
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
char *acpi_ut_get_mutex_name(u32 mutex_id);
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type);
#endif
char *acpi_ut_get_type_name(acpi_object_type type);
char *acpi_ut_get_node_name(void *object);
char *acpi_ut_get_descriptor_name(void *object);
const char *acpi_ut_get_reference_name(union acpi_operand_object *object);
char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
char *acpi_ut_get_region_name(u8 space_id);
char *acpi_ut_get_event_name(u32 event_id);
char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
u8 acpi_ut_ascii_char_to_hex(int hex_char);
u8 acpi_ut_valid_object_type(acpi_object_type type);
/*
* utinit - miscellaneous initialization and shutdown
*/
acpi_status acpi_ut_hardware_initialize(void);
void acpi_ut_subsystem_shutdown(void);
/*
* utcopy - Object construction and conversion interfaces
*/
acpi_status
acpi_ut_build_simple_object(union acpi_operand_object *obj,
union acpi_object *user_obj,
u8 *data_space, u32 *buffer_space_used);
acpi_status
acpi_ut_build_package_object(union acpi_operand_object *obj,
u8 *buffer, u32 *space_used);
acpi_status
acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj,
struct acpi_buffer *ret_buffer);
acpi_status
acpi_ut_copy_eobject_to_iobject(union acpi_object *obj,
union acpi_operand_object **internal_obj);
acpi_status
acpi_ut_copy_isimple_to_isimple(union acpi_operand_object *source_obj,
union acpi_operand_object *dest_obj);
acpi_status
acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
union acpi_operand_object **dest_desc,
struct acpi_walk_state *walk_state);
/*
* utcreate - Object creation
*/
acpi_status
acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action);
/*
* utdebug - Debug interfaces
*/
void acpi_ut_init_stack_ptr_trace(void);
void acpi_ut_track_stack_ptr(void);
void
acpi_ut_trace(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id);
void
acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, void *pointer);
void
acpi_ut_trace_u32(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, u32 integer);
void
acpi_ut_trace_str(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, char *string);
void
acpi_ut_exit(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id);
void
acpi_ut_status_exit(u32 line_number,
const char *function_name,
const char *module_name,
u32 component_id, acpi_status status);
void
acpi_ut_value_exit(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, u64 value);
void
acpi_ut_ptr_exit(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, u8 *ptr);
void
acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id);
void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
#ifdef ACPI_APPLICATION
void
acpi_ut_dump_buffer_to_file(ACPI_FILE file,
u8 *buffer,
u32 count, u32 display, u32 base_offset);
#endif
void acpi_ut_report_error(char *module_name, u32 line_number);
void acpi_ut_report_info(char *module_name, u32 line_number);
void acpi_ut_report_warning(char *module_name, u32 line_number);
/*
* utdelete - Object deletion and reference counts
*/
void acpi_ut_add_reference(union acpi_operand_object *object);
void acpi_ut_remove_reference(union acpi_operand_object *object);
void acpi_ut_delete_internal_package_object(union acpi_operand_object *object);
void acpi_ut_delete_internal_simple_object(union acpi_operand_object *object);
void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
/*
* uteval - object evaluation
*/
acpi_status
acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
char *path,
u32 expected_return_btypes,
union acpi_operand_object **return_desc);
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
struct acpi_namespace_node *device_node,
u64 *value);
acpi_status
acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 *status_flags);
acpi_status
acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
const char **method_names,
u8 method_count, u8 *out_values);
/*
* utfileio - file operations
*/
#ifdef ACPI_APPLICATION
acpi_status
acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table);
#endif
/*
* utids - device ID support
*/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id ** return_id);
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id ** return_id);
acpi_status
acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id **return_id);
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id_list ** return_cid_list);
acpi_status
acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id **return_id);
/*
* utlock - reader/writer locks
*/
acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock);
void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock);
acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock);
acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock);
acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock);
void acpi_ut_release_write_lock(struct acpi_rw_lock *lock);
/*
* utobject - internal object create/delete/cache routines
*/
union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
*module_name,
u32 line_number,
u32 component_id,
acpi_object_type
type);
void *acpi_ut_allocate_object_desc_dbg(const char *module_name,
u32 line_number, u32 component_id);
#define acpi_ut_create_internal_object(t) acpi_ut_create_internal_object_dbg (_acpi_module_name,__LINE__,_COMPONENT,t)
#define acpi_ut_allocate_object_desc() acpi_ut_allocate_object_desc_dbg (_acpi_module_name,__LINE__,_COMPONENT)
void acpi_ut_delete_object_desc(union acpi_operand_object *object);
u8 acpi_ut_valid_internal_object(void *object);
union acpi_operand_object *acpi_ut_create_package_object(u32 count);
union acpi_operand_object *acpi_ut_create_integer_object(u64 value);
union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
acpi_status
acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
/*
* utosi - Support for the _OSI predefined control method
*/
acpi_status acpi_ut_initialize_interfaces(void);
acpi_status acpi_ut_interface_terminate(void);
acpi_status acpi_ut_install_interface(acpi_string interface_name);
acpi_status acpi_ut_remove_interface(acpi_string interface_name);
acpi_status acpi_ut_update_interfaces(u8 action);
struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
/*
* utpredef - support for predefined names
*/
const union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union
acpi_predefined_info
*this_name);
const union acpi_predefined_info *acpi_ut_match_predefined_method(char *name);
void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes);
#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP)
const union acpi_predefined_info *acpi_ut_match_resource_name(char *name);
void
acpi_ut_display_predefined_method(char *buffer,
const union acpi_predefined_info *this_name,
u8 multi_line);
u32 acpi_ut_get_resource_bit_width(char *buffer, u16 types);
#endif
/*
* utstate - Generic state creation/cache routines
*/
void
acpi_ut_push_generic_state(union acpi_generic_state **list_head,
union acpi_generic_state *state);
union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
**list_head);
union acpi_generic_state *acpi_ut_create_generic_state(void);
struct acpi_thread_state *acpi_ut_create_thread_state(void);
union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
*object, u16 action);
union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
void *external_object,
u16 index);
acpi_status
acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
u16 action,
union acpi_generic_state **state_list);
union acpi_generic_state *acpi_ut_create_control_state(void);
void acpi_ut_delete_generic_state(union acpi_generic_state *state);
/*
* utmath
*/
acpi_status
acpi_ut_divide(u64 in_dividend,
u64 in_divisor, u64 *out_quotient, u64 *out_remainder);
acpi_status
acpi_ut_short_divide(u64 in_dividend,
u32 divisor, u64 *out_quotient, u32 *out_remainder);
/*
* utmisc
*/
const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status
status);
u8 acpi_ut_is_pci_root_bridge(char *id);
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
#endif
acpi_status
acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
void *target_object,
acpi_pkg_callback walk_callback, void *context);
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0
u32 acpi_ut_dword_byte_swap(u32 value);
void acpi_ut_set_integer_width(u8 revision);
#ifdef ACPI_DEBUG_OUTPUT
void
acpi_ut_display_init_pathname(u8 type,
struct acpi_namespace_node *obj_handle,
char *path);
#endif
/*
* utownerid - Support for Table/Method Owner IDs
*/
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
void acpi_ut_release_owner_id(acpi_owner_id * owner_id);
/*
* utresrc
*/
acpi_status
acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
u8 *aml,
acpi_size aml_length,
acpi_walk_aml_callback user_function,
void **context);
acpi_status
acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
void *aml, u8 *return_index);
u32 acpi_ut_get_descriptor_length(void *aml);
u16 acpi_ut_get_resource_length(void *aml);
u8 acpi_ut_get_resource_header_length(void *aml);
u8 acpi_ut_get_resource_type(void *aml);
acpi_status
acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag);
/*
* utstring - String and character utilities
*/
void acpi_ut_print_string(char *string, u16 max_length);
#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
void ut_convert_backslashes(char *pathname);
#endif
u8 acpi_ut_valid_acpi_name(char *name);
u8 acpi_ut_valid_acpi_char(char character, u32 position);
void acpi_ut_repair_name(char *name);
#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source);
u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source);
u8
acpi_ut_safe_strncat(char *dest,
acpi_size dest_size,
char *source, acpi_size max_transfer_length);
#endif
/*
* utmutex - mutex support
*/
acpi_status acpi_ut_mutex_initialize(void);
void acpi_ut_mutex_terminate(void);
acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id);
acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id);
/*
* utalloc - memory allocation and object caching
*/
acpi_status acpi_ut_create_caches(void);
acpi_status acpi_ut_delete_caches(void);
acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer);
acpi_status
acpi_ut_initialize_buffer(struct acpi_buffer *buffer,
acpi_size required_length);
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
void *acpi_ut_allocate_and_track(acpi_size size,
u32 component, const char *module, u32 line);
void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
u32 component,
const char *module, u32 line);
void
acpi_ut_free_and_track(void *address,
u32 component, const char *module, u32 line);
void acpi_ut_dump_allocation_info(void);
void acpi_ut_dump_allocations(u32 component, const char *module);
acpi_status
acpi_ut_create_list(char *list_name,
u16 object_size, struct acpi_memory_list **return_cache);
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
/*
* utaddress - address range check
*/
acpi_status
acpi_ut_add_address_range(acpi_adr_space_type space_id,
acpi_physical_address address,
u32 length, struct acpi_namespace_node *region_node);
void
acpi_ut_remove_address_range(acpi_adr_space_type space_id,
struct acpi_namespace_node *region_node);
u32
acpi_ut_check_address_range(acpi_adr_space_type space_id,
acpi_physical_address address, u32 length, u8 warn);
void acpi_ut_delete_address_lists(void);
/*
* utxferror - various error/warning output functions
*/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_info(const char *module_name,
u32 line_number,
char *pathname, u8 node_flags, const char *format, ...);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_bios_error(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
void
acpi_ut_namespace_error(const char *module_name,
u32 line_number,
const char *internal_name, acpi_status lookup_status);
void
acpi_ut_method_error(const char *module_name,
u32 line_number,
const char *message,
struct acpi_namespace_node *node,
const char *path, acpi_status lookup_status);
/*
* Utility functions for ACPI names and IDs
*/
const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg);
const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
const char *acpi_ah_match_uuid(u8 *data);
/*
* utprint - printf/vprintf output functions
*/
const char *acpi_ut_scan_number(const char *string, u64 *number_ptr);
const char *acpi_ut_print_number(char *string, u64 number);
int
acpi_ut_vsnprintf(char *string,
acpi_size size, const char *format, va_list args);
int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...);
#ifdef ACPI_APPLICATION
int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args);
int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...);
#endif
/*
* utuuid -- UUID support functions
*/
#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_HELP_APP)
void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer);
#endif
#endif /* _ACUTILS_H */

View File

@@ -1,488 +0,0 @@
/******************************************************************************
*
* Name: amlcode.h - Definitions for AML, as included in "definition blocks"
* Declarations and definitions contained herein are derived
* directly from the ACPI specification.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __AMLCODE_H__
#define __AMLCODE_H__
/* primary opcodes */
#define AML_NULL_CHAR (u16) 0x00
#define AML_ZERO_OP (u16) 0x00
#define AML_ONE_OP (u16) 0x01
#define AML_UNASSIGNED (u16) 0x02
#define AML_ALIAS_OP (u16) 0x06
#define AML_NAME_OP (u16) 0x08
#define AML_BYTE_OP (u16) 0x0a
#define AML_WORD_OP (u16) 0x0b
#define AML_DWORD_OP (u16) 0x0c
#define AML_STRING_OP (u16) 0x0d
#define AML_QWORD_OP (u16) 0x0e /* ACPI 2.0 */
#define AML_SCOPE_OP (u16) 0x10
#define AML_BUFFER_OP (u16) 0x11
#define AML_PACKAGE_OP (u16) 0x12
#define AML_VAR_PACKAGE_OP (u16) 0x13 /* ACPI 2.0 */
#define AML_METHOD_OP (u16) 0x14
#define AML_EXTERNAL_OP (u16) 0x15 /* ACPI 6.0 */
#define AML_DUAL_NAME_PREFIX (u16) 0x2e
#define AML_MULTI_NAME_PREFIX_OP (u16) 0x2f
#define AML_NAME_CHAR_SUBSEQ (u16) 0x30
#define AML_NAME_CHAR_FIRST (u16) 0x41
#define AML_EXTENDED_OP_PREFIX (u16) 0x5b
#define AML_ROOT_PREFIX (u16) 0x5c
#define AML_PARENT_PREFIX (u16) 0x5e
#define AML_LOCAL_OP (u16) 0x60
#define AML_LOCAL0 (u16) 0x60
#define AML_LOCAL1 (u16) 0x61
#define AML_LOCAL2 (u16) 0x62
#define AML_LOCAL3 (u16) 0x63
#define AML_LOCAL4 (u16) 0x64
#define AML_LOCAL5 (u16) 0x65
#define AML_LOCAL6 (u16) 0x66
#define AML_LOCAL7 (u16) 0x67
#define AML_ARG_OP (u16) 0x68
#define AML_ARG0 (u16) 0x68
#define AML_ARG1 (u16) 0x69
#define AML_ARG2 (u16) 0x6a
#define AML_ARG3 (u16) 0x6b
#define AML_ARG4 (u16) 0x6c
#define AML_ARG5 (u16) 0x6d
#define AML_ARG6 (u16) 0x6e
#define AML_STORE_OP (u16) 0x70
#define AML_REF_OF_OP (u16) 0x71
#define AML_ADD_OP (u16) 0x72
#define AML_CONCAT_OP (u16) 0x73
#define AML_SUBTRACT_OP (u16) 0x74
#define AML_INCREMENT_OP (u16) 0x75
#define AML_DECREMENT_OP (u16) 0x76
#define AML_MULTIPLY_OP (u16) 0x77
#define AML_DIVIDE_OP (u16) 0x78
#define AML_SHIFT_LEFT_OP (u16) 0x79
#define AML_SHIFT_RIGHT_OP (u16) 0x7a
#define AML_BIT_AND_OP (u16) 0x7b
#define AML_BIT_NAND_OP (u16) 0x7c
#define AML_BIT_OR_OP (u16) 0x7d
#define AML_BIT_NOR_OP (u16) 0x7e
#define AML_BIT_XOR_OP (u16) 0x7f
#define AML_BIT_NOT_OP (u16) 0x80
#define AML_FIND_SET_LEFT_BIT_OP (u16) 0x81
#define AML_FIND_SET_RIGHT_BIT_OP (u16) 0x82
#define AML_DEREF_OF_OP (u16) 0x83
#define AML_CONCAT_RES_OP (u16) 0x84 /* ACPI 2.0 */
#define AML_MOD_OP (u16) 0x85 /* ACPI 2.0 */
#define AML_NOTIFY_OP (u16) 0x86
#define AML_SIZE_OF_OP (u16) 0x87
#define AML_INDEX_OP (u16) 0x88
#define AML_MATCH_OP (u16) 0x89
#define AML_CREATE_DWORD_FIELD_OP (u16) 0x8a
#define AML_CREATE_WORD_FIELD_OP (u16) 0x8b
#define AML_CREATE_BYTE_FIELD_OP (u16) 0x8c
#define AML_CREATE_BIT_FIELD_OP (u16) 0x8d
#define AML_TYPE_OP (u16) 0x8e
#define AML_CREATE_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */
#define AML_LAND_OP (u16) 0x90
#define AML_LOR_OP (u16) 0x91
#define AML_LNOT_OP (u16) 0x92
#define AML_LEQUAL_OP (u16) 0x93
#define AML_LGREATER_OP (u16) 0x94
#define AML_LLESS_OP (u16) 0x95
#define AML_TO_BUFFER_OP (u16) 0x96 /* ACPI 2.0 */
#define AML_TO_DECSTRING_OP (u16) 0x97 /* ACPI 2.0 */
#define AML_TO_HEXSTRING_OP (u16) 0x98 /* ACPI 2.0 */
#define AML_TO_INTEGER_OP (u16) 0x99 /* ACPI 2.0 */
#define AML_TO_STRING_OP (u16) 0x9c /* ACPI 2.0 */
#define AML_COPY_OP (u16) 0x9d /* ACPI 2.0 */
#define AML_MID_OP (u16) 0x9e /* ACPI 2.0 */
#define AML_CONTINUE_OP (u16) 0x9f /* ACPI 2.0 */
#define AML_IF_OP (u16) 0xa0
#define AML_ELSE_OP (u16) 0xa1
#define AML_WHILE_OP (u16) 0xa2
#define AML_NOOP_OP (u16) 0xa3
#define AML_RETURN_OP (u16) 0xa4
#define AML_BREAK_OP (u16) 0xa5
#define AML_BREAK_POINT_OP (u16) 0xcc
#define AML_ONES_OP (u16) 0xff
/* prefixed opcodes */
#define AML_EXTENDED_OPCODE (u16) 0x5b00 /* prefix for 2-byte opcodes */
#define AML_MUTEX_OP (u16) 0x5b01
#define AML_EVENT_OP (u16) 0x5b02
#define AML_SHIFT_RIGHT_BIT_OP (u16) 0x5b10
#define AML_SHIFT_LEFT_BIT_OP (u16) 0x5b11
#define AML_COND_REF_OF_OP (u16) 0x5b12
#define AML_CREATE_FIELD_OP (u16) 0x5b13
#define AML_LOAD_TABLE_OP (u16) 0x5b1f /* ACPI 2.0 */
#define AML_LOAD_OP (u16) 0x5b20
#define AML_STALL_OP (u16) 0x5b21
#define AML_SLEEP_OP (u16) 0x5b22
#define AML_ACQUIRE_OP (u16) 0x5b23
#define AML_SIGNAL_OP (u16) 0x5b24
#define AML_WAIT_OP (u16) 0x5b25
#define AML_RESET_OP (u16) 0x5b26
#define AML_RELEASE_OP (u16) 0x5b27
#define AML_FROM_BCD_OP (u16) 0x5b28
#define AML_TO_BCD_OP (u16) 0x5b29
#define AML_UNLOAD_OP (u16) 0x5b2a
#define AML_REVISION_OP (u16) 0x5b30
#define AML_DEBUG_OP (u16) 0x5b31
#define AML_FATAL_OP (u16) 0x5b32
#define AML_TIMER_OP (u16) 0x5b33 /* ACPI 3.0 */
#define AML_REGION_OP (u16) 0x5b80
#define AML_FIELD_OP (u16) 0x5b81
#define AML_DEVICE_OP (u16) 0x5b82
#define AML_PROCESSOR_OP (u16) 0x5b83
#define AML_POWER_RES_OP (u16) 0x5b84
#define AML_THERMAL_ZONE_OP (u16) 0x5b85
#define AML_INDEX_FIELD_OP (u16) 0x5b86
#define AML_BANK_FIELD_OP (u16) 0x5b87
#define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */
/*
* Combination opcodes (actually two one-byte opcodes)
* Used by the disassembler and iASL compiler
*/
#define AML_LGREATEREQUAL_OP (u16) 0x9295
#define AML_LLESSEQUAL_OP (u16) 0x9294
#define AML_LNOTEQUAL_OP (u16) 0x9293
/*
* Opcodes for "Field" operators
*/
#define AML_FIELD_OFFSET_OP (u8) 0x00
#define AML_FIELD_ACCESS_OP (u8) 0x01
#define AML_FIELD_CONNECTION_OP (u8) 0x02 /* ACPI 5.0 */
#define AML_FIELD_EXT_ACCESS_OP (u8) 0x03 /* ACPI 5.0 */
/*
* Internal opcodes
* Use only "Unknown" AML opcodes, don't attempt to use
* any valid ACPI ASCII values (A-Z, 0-9, '-')
*/
#define AML_INT_NAMEPATH_OP (u16) 0x002d
#define AML_INT_NAMEDFIELD_OP (u16) 0x0030
#define AML_INT_RESERVEDFIELD_OP (u16) 0x0031
#define AML_INT_ACCESSFIELD_OP (u16) 0x0032
#define AML_INT_BYTELIST_OP (u16) 0x0033
#define AML_INT_METHODCALL_OP (u16) 0x0035
#define AML_INT_RETURN_VALUE_OP (u16) 0x0036
#define AML_INT_EVAL_SUBTREE_OP (u16) 0x0037
#define AML_INT_CONNECTION_OP (u16) 0x0038
#define AML_INT_EXTACCESSFIELD_OP (u16) 0x0039
#define ARG_NONE 0x0
/*
* Argument types for the AML Parser
* Each field in the arg_types u32 is 5 bits, allowing for a maximum of 6 arguments.
* There can be up to 31 unique argument types
* Zero is reserved as end-of-list indicator
*/
#define ARGP_BYTEDATA 0x01
#define ARGP_BYTELIST 0x02
#define ARGP_CHARLIST 0x03
#define ARGP_DATAOBJ 0x04
#define ARGP_DATAOBJLIST 0x05
#define ARGP_DWORDDATA 0x06
#define ARGP_FIELDLIST 0x07
#define ARGP_NAME 0x08
#define ARGP_NAMESTRING 0x09
#define ARGP_OBJLIST 0x0A
#define ARGP_PKGLENGTH 0x0B
#define ARGP_SUPERNAME 0x0C
#define ARGP_TARGET 0x0D
#define ARGP_TERMARG 0x0E
#define ARGP_TERMLIST 0x0F
#define ARGP_WORDDATA 0x10
#define ARGP_QWORDDATA 0x11
#define ARGP_SIMPLENAME 0x12
/*
* Resolved argument types for the AML Interpreter
* Each field in the arg_types u32 is 5 bits, allowing for a maximum of 6 arguments.
* There can be up to 31 unique argument types (0 is end-of-arg-list indicator)
*
* Note1: These values are completely independent from the ACPI_TYPEs
* i.e., ARGI_INTEGER != ACPI_TYPE_INTEGER
*
* Note2: If and when 5 bits becomes insufficient, it would probably be best
* to convert to a 6-byte array of argument types, allowing 8 bits per argument.
*/
/* Single, simple types */
#define ARGI_ANYTYPE 0x01 /* Don't care */
#define ARGI_PACKAGE 0x02
#define ARGI_EVENT 0x03
#define ARGI_MUTEX 0x04
#define ARGI_DDBHANDLE 0x05
/* Interchangeable types (via implicit conversion) */
#define ARGI_INTEGER 0x06
#define ARGI_STRING 0x07
#define ARGI_BUFFER 0x08
#define ARGI_BUFFER_OR_STRING 0x09 /* Used by MID op only */
#define ARGI_COMPUTEDATA 0x0A /* Buffer, String, or Integer */
/* Reference objects */
#define ARGI_INTEGER_REF 0x0B
#define ARGI_OBJECT_REF 0x0C
#define ARGI_DEVICE_REF 0x0D
#define ARGI_REFERENCE 0x0E
#define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */
#define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */
#define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */
#define ARGI_STORE_TARGET 0x12 /* Target for store is TARGETREF + package objects */
/* Multiple/complex types */
#define ARGI_DATAOBJECT 0x13 /* Buffer, String, package or reference to a node - Used only by size_of operator */
#define ARGI_COMPLEXOBJ 0x14 /* Buffer, String, or package (Used by INDEX op only) */
#define ARGI_REF_OR_STRING 0x15 /* Reference or String (Used by DEREFOF op only) */
#define ARGI_REGION_OR_BUFFER 0x16 /* Used by LOAD op only */
#define ARGI_DATAREFOBJ 0x17
/* Note: types above can expand to 0x1F maximum */
#define ARGI_INVALID_OPCODE 0xFFFFFFFF
/*
* hash offsets
*/
#define AML_EXTOP_HASH_OFFSET 22
#define AML_LNOT_HASH_OFFSET 19
/*
* opcode groups and types
*/
#define OPGRP_NAMED 0x01
#define OPGRP_FIELD 0x02
#define OPGRP_BYTELIST 0x04
/*
* Opcode information
*/
/* Opcode flags */
#define AML_LOGICAL 0x0001
#define AML_LOGICAL_NUMERIC 0x0002
#define AML_MATH 0x0004
#define AML_CREATE 0x0008
#define AML_FIELD 0x0010
#define AML_DEFER 0x0020
#define AML_NAMED 0x0040
#define AML_NSNODE 0x0080
#define AML_NSOPCODE 0x0100
#define AML_NSOBJECT 0x0200
#define AML_HAS_RETVAL 0x0400
#define AML_HAS_TARGET 0x0800
#define AML_HAS_ARGS 0x1000
#define AML_CONSTANT 0x2000
#define AML_NO_OPERAND_RESOLVE 0x4000
/* Convenient flag groupings */
#define AML_FLAGS_EXEC_0A_0T_1R AML_HAS_RETVAL
#define AML_FLAGS_EXEC_1A_0T_0R AML_HAS_ARGS /* Monadic1 */
#define AML_FLAGS_EXEC_1A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Monadic2 */
#define AML_FLAGS_EXEC_1A_1T_0R AML_HAS_ARGS | AML_HAS_TARGET
#define AML_FLAGS_EXEC_1A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* monadic2_r */
#define AML_FLAGS_EXEC_2A_0T_0R AML_HAS_ARGS /* Dyadic1 */
#define AML_FLAGS_EXEC_2A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL /* Dyadic2 */
#define AML_FLAGS_EXEC_2A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL /* dyadic2_r */
#define AML_FLAGS_EXEC_2A_2T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL
#define AML_FLAGS_EXEC_3A_0T_0R AML_HAS_ARGS
#define AML_FLAGS_EXEC_3A_1T_1R AML_HAS_ARGS | AML_HAS_TARGET | AML_HAS_RETVAL
#define AML_FLAGS_EXEC_6A_0T_1R AML_HAS_ARGS | AML_HAS_RETVAL
/*
* The opcode Type is used in a dispatch table, do not change
* without updating the table.
*/
#define AML_TYPE_EXEC_0A_0T_1R 0x00
#define AML_TYPE_EXEC_1A_0T_0R 0x01 /* Monadic1 */
#define AML_TYPE_EXEC_1A_0T_1R 0x02 /* Monadic2 */
#define AML_TYPE_EXEC_1A_1T_0R 0x03
#define AML_TYPE_EXEC_1A_1T_1R 0x04 /* monadic2_r */
#define AML_TYPE_EXEC_2A_0T_0R 0x05 /* Dyadic1 */
#define AML_TYPE_EXEC_2A_0T_1R 0x06 /* Dyadic2 */
#define AML_TYPE_EXEC_2A_1T_1R 0x07 /* dyadic2_r */
#define AML_TYPE_EXEC_2A_2T_1R 0x08
#define AML_TYPE_EXEC_3A_0T_0R 0x09
#define AML_TYPE_EXEC_3A_1T_1R 0x0A
#define AML_TYPE_EXEC_6A_0T_1R 0x0B
/* End of types used in dispatch table */
#define AML_TYPE_LITERAL 0x0B
#define AML_TYPE_CONSTANT 0x0C
#define AML_TYPE_METHOD_ARGUMENT 0x0D
#define AML_TYPE_LOCAL_VARIABLE 0x0E
#define AML_TYPE_DATA_TERM 0x0F
/* Generic for an op that returns a value */
#define AML_TYPE_METHOD_CALL 0x10
/* Misc */
#define AML_TYPE_CREATE_FIELD 0x11
#define AML_TYPE_CREATE_OBJECT 0x12
#define AML_TYPE_CONTROL 0x13
#define AML_TYPE_NAMED_NO_OBJ 0x14
#define AML_TYPE_NAMED_FIELD 0x15
#define AML_TYPE_NAMED_SIMPLE 0x16
#define AML_TYPE_NAMED_COMPLEX 0x17
#define AML_TYPE_RETURN 0x18
#define AML_TYPE_UNDEFINED 0x19
#define AML_TYPE_BOGUS 0x1A
/* AML Package Length encodings */
#define ACPI_AML_PACKAGE_TYPE1 0x40
#define ACPI_AML_PACKAGE_TYPE2 0x4000
#define ACPI_AML_PACKAGE_TYPE3 0x400000
#define ACPI_AML_PACKAGE_TYPE4 0x40000000
/*
* Opcode classes
*/
#define AML_CLASS_EXECUTE 0x00
#define AML_CLASS_CREATE 0x01
#define AML_CLASS_ARGUMENT 0x02
#define AML_CLASS_NAMED_OBJECT 0x03
#define AML_CLASS_CONTROL 0x04
#define AML_CLASS_ASCII 0x05
#define AML_CLASS_PREFIX 0x06
#define AML_CLASS_INTERNAL 0x07
#define AML_CLASS_RETURN_VALUE 0x08
#define AML_CLASS_METHOD_CALL 0x09
#define AML_CLASS_UNKNOWN 0x0A
/* Comparison operation codes for match_op operator */
typedef enum {
MATCH_MTR = 0,
MATCH_MEQ = 1,
MATCH_MLE = 2,
MATCH_MLT = 3,
MATCH_MGE = 4,
MATCH_MGT = 5
} AML_MATCH_OPERATOR;
#define MAX_MATCH_OPERATOR 5
/*
* field_flags
*
* This byte is extracted from the AML and includes three separate
* pieces of information about the field:
* 1) The field access type
* 2) The field update rule
* 3) The lock rule for the field
*
* Bits 00 - 03 : access_type (any_acc, byte_acc, etc.)
* 04 : lock_rule (1 == Lock)
* 05 - 06 : update_rule
*/
#define AML_FIELD_ACCESS_TYPE_MASK 0x0F
#define AML_FIELD_LOCK_RULE_MASK 0x10
#define AML_FIELD_UPDATE_RULE_MASK 0x60
/* 1) Field Access Types */
typedef enum {
AML_FIELD_ACCESS_ANY = 0x00,
AML_FIELD_ACCESS_BYTE = 0x01,
AML_FIELD_ACCESS_WORD = 0x02,
AML_FIELD_ACCESS_DWORD = 0x03,
AML_FIELD_ACCESS_QWORD = 0x04, /* ACPI 2.0 */
AML_FIELD_ACCESS_BUFFER = 0x05 /* ACPI 2.0 */
} AML_ACCESS_TYPE;
/* 2) Field Lock Rules */
typedef enum {
AML_FIELD_LOCK_NEVER = 0x00,
AML_FIELD_LOCK_ALWAYS = 0x10
} AML_LOCK_RULE;
/* 3) Field Update Rules */
typedef enum {
AML_FIELD_UPDATE_PRESERVE = 0x00,
AML_FIELD_UPDATE_WRITE_AS_ONES = 0x20,
AML_FIELD_UPDATE_WRITE_AS_ZEROS = 0x40
} AML_UPDATE_RULE;
/*
* Field Access Attributes.
* This byte is extracted from the AML via the
* access_as keyword
*/
typedef enum {
AML_FIELD_ATTRIB_QUICK = 0x02,
AML_FIELD_ATTRIB_SEND_RCV = 0x04,
AML_FIELD_ATTRIB_BYTE = 0x06,
AML_FIELD_ATTRIB_WORD = 0x08,
AML_FIELD_ATTRIB_BLOCK = 0x0A,
AML_FIELD_ATTRIB_MULTIBYTE = 0x0B,
AML_FIELD_ATTRIB_WORD_CALL = 0x0C,
AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D,
AML_FIELD_ATTRIB_RAW_BYTES = 0x0E,
AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F
} AML_ACCESS_ATTRIBUTE;
/* Bit fields in the AML method_flags byte */
#define AML_METHOD_ARG_COUNT 0x07
#define AML_METHOD_SERIALIZED 0x08
#define AML_METHOD_SYNC_LEVEL 0xF0
#endif /* __AMLCODE_H__ */

View File

@@ -1,486 +0,0 @@
/******************************************************************************
*
* Module Name: amlresrc.h - AML resource descriptors
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
/* acpisrc:struct_defs -- for acpisrc conversion */
#ifndef __AMLRESRC_H
#define __AMLRESRC_H
/*
* Resource descriptor tags, as defined in the ACPI specification.
* Used to symbolically reference fields within a descriptor.
*/
#define ACPI_RESTAG_ADDRESS "_ADR"
#define ACPI_RESTAG_ALIGNMENT "_ALN"
#define ACPI_RESTAG_ADDRESSSPACE "_ASI"
#define ACPI_RESTAG_ACCESSSIZE "_ASZ"
#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES "_ATT"
#define ACPI_RESTAG_BASEADDRESS "_BAS"
#define ACPI_RESTAG_BUSMASTER "_BM_" /* Master(1), Slave(0) */
#define ACPI_RESTAG_DEBOUNCETIME "_DBT"
#define ACPI_RESTAG_DECODE "_DEC"
#define ACPI_RESTAG_DEVICEPOLARITY "_DPL"
#define ACPI_RESTAG_DMA "_DMA"
#define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */
#define ACPI_RESTAG_DRIVESTRENGTH "_DRS"
#define ACPI_RESTAG_ENDIANNESS "_END"
#define ACPI_RESTAG_FLOWCONTROL "_FLC"
#define ACPI_RESTAG_GRANULARITY "_GRA"
#define ACPI_RESTAG_INTERRUPT "_INT"
#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */
#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */
#define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */
#define ACPI_RESTAG_IORESTRICTION "_IOR"
#define ACPI_RESTAG_LENGTH "_LEN"
#define ACPI_RESTAG_LINE "_LIN"
#define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */
#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
#define ACPI_RESTAG_MAXADDR "_MAX"
#define ACPI_RESTAG_MINADDR "_MIN"
#define ACPI_RESTAG_MAXTYPE "_MAF"
#define ACPI_RESTAG_MINTYPE "_MIF"
#define ACPI_RESTAG_MODE "_MOD"
#define ACPI_RESTAG_PARITY "_PAR"
#define ACPI_RESTAG_PHASE "_PHA"
#define ACPI_RESTAG_PIN "_PIN"
#define ACPI_RESTAG_PINCONFIG "_PPI"
#define ACPI_RESTAG_POLARITY "_POL"
#define ACPI_RESTAG_REGISTERBITOFFSET "_RBO"
#define ACPI_RESTAG_REGISTERBITWIDTH "_RBW"
#define ACPI_RESTAG_RANGETYPE "_RNG"
#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */
#define ACPI_RESTAG_LENGTH_RX "_RXL"
#define ACPI_RESTAG_LENGTH_TX "_TXL"
#define ACPI_RESTAG_SLAVEMODE "_SLV"
#define ACPI_RESTAG_SPEED "_SPE"
#define ACPI_RESTAG_STOPBITS "_STB"
#define ACPI_RESTAG_TRANSLATION "_TRA"
#define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */
#define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */
#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8And16(1), 16(2) */
#define ACPI_RESTAG_VENDORDATA "_VEN"
/* Default sizes for "small" resource descriptors */
#define ASL_RDESC_IRQ_SIZE 0x02
#define ASL_RDESC_DMA_SIZE 0x02
#define ASL_RDESC_ST_DEPEND_SIZE 0x00
#define ASL_RDESC_END_DEPEND_SIZE 0x00
#define ASL_RDESC_IO_SIZE 0x07
#define ASL_RDESC_FIXED_IO_SIZE 0x03
#define ASL_RDESC_FIXED_DMA_SIZE 0x05
#define ASL_RDESC_END_TAG_SIZE 0x01
struct asl_resource_node {
u32 buffer_length;
void *buffer;
struct asl_resource_node *next;
};
struct asl_resource_info {
union acpi_parse_object *descriptor_type_op; /* Resource descriptor parse node */
union acpi_parse_object *mapping_op; /* Used for mapfile support */
u32 current_byte_offset; /* Offset in resource template */
};
/* Macros used to generate AML resource length fields */
#define ACPI_AML_SIZE_LARGE(r) (sizeof (r) - sizeof (struct aml_resource_large_header))
#define ACPI_AML_SIZE_SMALL(r) (sizeof (r) - sizeof (struct aml_resource_small_header))
/*
* Resource descriptors defined in the ACPI specification.
*
* Packing/alignment must be BYTE because these descriptors
* are used to overlay the raw AML byte stream.
*/
#pragma pack(1)
/*
* SMALL descriptors
*/
#define AML_RESOURCE_SMALL_HEADER_COMMON \
u8 descriptor_type;
struct aml_resource_small_header {
AML_RESOURCE_SMALL_HEADER_COMMON};
struct aml_resource_irq {
AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask;
u8 flags;
};
struct aml_resource_irq_noflags {
AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask;
};
struct aml_resource_dma {
AML_RESOURCE_SMALL_HEADER_COMMON u8 dma_channel_mask;
u8 flags;
};
struct aml_resource_start_dependent {
AML_RESOURCE_SMALL_HEADER_COMMON u8 flags;
};
struct aml_resource_start_dependent_noprio {
AML_RESOURCE_SMALL_HEADER_COMMON};
struct aml_resource_end_dependent {
AML_RESOURCE_SMALL_HEADER_COMMON};
struct aml_resource_io {
AML_RESOURCE_SMALL_HEADER_COMMON u8 flags;
u16 minimum;
u16 maximum;
u8 alignment;
u8 address_length;
};
struct aml_resource_fixed_io {
AML_RESOURCE_SMALL_HEADER_COMMON u16 address;
u8 address_length;
};
struct aml_resource_vendor_small {
AML_RESOURCE_SMALL_HEADER_COMMON};
struct aml_resource_end_tag {
AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum;
};
struct aml_resource_fixed_dma {
AML_RESOURCE_SMALL_HEADER_COMMON u16 request_lines;
u16 channels;
u8 width;
};
/*
* LARGE descriptors
*/
#define AML_RESOURCE_LARGE_HEADER_COMMON \
u8 descriptor_type;\
u16 resource_length;
struct aml_resource_large_header {
AML_RESOURCE_LARGE_HEADER_COMMON};
/* General Flags for address space resource descriptors */
#define ACPI_RESOURCE_FLAG_DEC 2
#define ACPI_RESOURCE_FLAG_MIF 4
#define ACPI_RESOURCE_FLAG_MAF 8
struct aml_resource_memory24 {
AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
u16 minimum;
u16 maximum;
u16 alignment;
u16 address_length;
};
struct aml_resource_vendor_large {
AML_RESOURCE_LARGE_HEADER_COMMON};
struct aml_resource_memory32 {
AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
u32 minimum;
u32 maximum;
u32 alignment;
u32 address_length;
};
struct aml_resource_fixed_memory32 {
AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
u32 address;
u32 address_length;
};
#define AML_RESOURCE_ADDRESS_COMMON \
u8 resource_type; \
u8 flags; \
u8 specific_flags;
struct aml_resource_address {
AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON};
struct aml_resource_extended_address64 {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_ADDRESS_COMMON u8 revision_ID;
u8 reserved;
u64 granularity;
u64 minimum;
u64 maximum;
u64 translation_offset;
u64 address_length;
u64 type_specific;
};
#define AML_RESOURCE_EXTENDED_ADDRESS_REVISION 1 /* ACPI 3.0 */
struct aml_resource_address64 {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_ADDRESS_COMMON u64 granularity;
u64 minimum;
u64 maximum;
u64 translation_offset;
u64 address_length;
};
struct aml_resource_address32 {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_ADDRESS_COMMON u32 granularity;
u32 minimum;
u32 maximum;
u32 translation_offset;
u32 address_length;
};
struct aml_resource_address16 {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_ADDRESS_COMMON u16 granularity;
u16 minimum;
u16 maximum;
u16 translation_offset;
u16 address_length;
};
struct aml_resource_extended_irq {
AML_RESOURCE_LARGE_HEADER_COMMON u8 flags;
u8 interrupt_count;
u32 interrupts[1];
/* res_source_index, res_source optional fields follow */
};
struct aml_resource_generic_register {
AML_RESOURCE_LARGE_HEADER_COMMON u8 address_space_id;
u8 bit_width;
u8 bit_offset;
u8 access_size; /* ACPI 3.0, was previously Reserved */
u64 address;
};
/* Common descriptor for gpio_int and gpio_io (ACPI 5.0) */
struct aml_resource_gpio {
AML_RESOURCE_LARGE_HEADER_COMMON u8 revision_id;
u8 connection_type;
u16 flags;
u16 int_flags;
u8 pin_config;
u16 drive_strength;
u16 debounce_timeout;
u16 pin_table_offset;
u8 res_source_index;
u16 res_source_offset;
u16 vendor_offset;
u16 vendor_length;
/*
* Optional fields follow immediately:
* 1) PIN list (Words)
* 2) Resource Source String
* 3) Vendor Data bytes
*/
};
#define AML_RESOURCE_GPIO_REVISION 1 /* ACPI 5.0 */
/* Values for connection_type above */
#define AML_RESOURCE_GPIO_TYPE_INT 0
#define AML_RESOURCE_GPIO_TYPE_IO 1
#define AML_RESOURCE_MAX_GPIOTYPE 1
/* Common preamble for all serial descriptors (ACPI 5.0) */
#define AML_RESOURCE_SERIAL_COMMON \
u8 revision_id; \
u8 res_source_index; \
u8 type; \
u8 flags; \
u16 type_specific_flags; \
u8 type_revision_id; \
u16 type_data_length; \
/* Values for the type field above */
#define AML_RESOURCE_I2C_SERIALBUSTYPE 1
#define AML_RESOURCE_SPI_SERIALBUSTYPE 2
#define AML_RESOURCE_UART_SERIALBUSTYPE 3
#define AML_RESOURCE_MAX_SERIALBUSTYPE 3
#define AML_RESOURCE_VENDOR_SERIALBUSTYPE 192 /* Vendor defined is 0xC0-0xFF (NOT SUPPORTED) */
struct aml_resource_common_serialbus {
AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_SERIAL_COMMON};
struct aml_resource_i2c_serialbus {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
u16 slave_address;
/*
* Optional fields follow immediately:
* 1) Vendor Data bytes
* 2) Resource Source String
*/
};
#define AML_RESOURCE_I2C_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_I2C_TYPE_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_I2C_MIN_DATA_LEN 6
struct aml_resource_spi_serialbus {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
u8 data_bit_length;
u8 clock_phase;
u8 clock_polarity;
u16 device_selection;
/*
* Optional fields follow immediately:
* 1) Vendor Data bytes
* 2) Resource Source String
*/
};
#define AML_RESOURCE_SPI_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_SPI_TYPE_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_SPI_MIN_DATA_LEN 9
struct aml_resource_uart_serialbus {
AML_RESOURCE_LARGE_HEADER_COMMON
AML_RESOURCE_SERIAL_COMMON u32 default_baud_rate;
u16 rx_fifo_size;
u16 tx_fifo_size;
u8 parity;
u8 lines_enabled;
/*
* Optional fields follow immediately:
* 1) Vendor Data bytes
* 2) Resource Source String
*/
};
#define AML_RESOURCE_UART_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_UART_TYPE_REVISION 1 /* ACPI 5.0 */
#define AML_RESOURCE_UART_MIN_DATA_LEN 10
/* restore default alignment */
#pragma pack()
/* Union of all resource descriptors, so we can allocate the worst case */
union aml_resource {
/* Descriptor headers */
u8 descriptor_type;
struct aml_resource_small_header small_header;
struct aml_resource_large_header large_header;
/* Small resource descriptors */
struct aml_resource_irq irq;
struct aml_resource_dma dma;
struct aml_resource_start_dependent start_dpf;
struct aml_resource_end_dependent end_dpf;
struct aml_resource_io io;
struct aml_resource_fixed_io fixed_io;
struct aml_resource_fixed_dma fixed_dma;
struct aml_resource_vendor_small vendor_small;
struct aml_resource_end_tag end_tag;
/* Large resource descriptors */
struct aml_resource_memory24 memory24;
struct aml_resource_generic_register generic_reg;
struct aml_resource_vendor_large vendor_large;
struct aml_resource_memory32 memory32;
struct aml_resource_fixed_memory32 fixed_memory32;
struct aml_resource_address16 address16;
struct aml_resource_address32 address32;
struct aml_resource_address64 address64;
struct aml_resource_extended_address64 ext_address64;
struct aml_resource_extended_irq extended_irq;
struct aml_resource_gpio gpio;
struct aml_resource_i2c_serialbus i2c_serial_bus;
struct aml_resource_spi_serialbus spi_serial_bus;
struct aml_resource_uart_serialbus uart_serial_bus;
struct aml_resource_common_serialbus common_serial_bus;
/* Utility overlays */
struct aml_resource_address address;
u32 dword_item;
u16 word_item;
u8 byte_item;
};
/* Interfaces used by both the disassembler and compiler */
void
mp_save_gpio_info(union acpi_parse_object *op,
union aml_resource *resource,
u32 pin_count, u16 *pin_list, char *device_name);
void
mp_save_serial_info(union acpi_parse_object *op,
union aml_resource *resource, char *device_name);
char *mp_get_hid_from_parse_tree(struct acpi_namespace_node *hid_node);
char *mp_get_hid_via_namestring(char *device_name);
char *mp_get_connection_info(union acpi_parse_object *op,
u32 pin_index,
struct acpi_namespace_node **target_node,
char **target_name);
char *mp_get_parent_device_hid(union acpi_parse_object *op,
struct acpi_namespace_node **target_node,
char **parent_device_name);
char *mp_get_ddn_value(char *device_name);
char *mp_get_hid_value(struct acpi_namespace_node *device_node);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,484 +0,0 @@
/*******************************************************************************
*
* Module Name: dbconvert - debugger miscellaneous conversion routines
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbconvert")
#define DB_DEFAULT_PKG_ELEMENTS 33
/*******************************************************************************
*
* FUNCTION: acpi_db_hex_char_to_value
*
* PARAMETERS: hex_char - Ascii Hex digit, 0-9|a-f|A-F
* return_value - Where the converted value is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
*
******************************************************************************/
acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value)
{
u8 value;
/* Digit must be ascii [0-9a-fA-F] */
if (!isxdigit(hex_char)) {
return (AE_BAD_HEX_CONSTANT);
}
if (hex_char <= 0x39) {
value = (u8)(hex_char - 0x30);
} else {
value = (u8)(toupper(hex_char) - 0x37);
}
*return_value = value;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_hex_byte_to_binary
*
* PARAMETERS: hex_byte - Double hex digit (0x00 - 0xFF) in format:
* hi_byte then lo_byte.
* return_value - Where the converted value is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
*
******************************************************************************/
static acpi_status acpi_db_hex_byte_to_binary(char *hex_byte, u8 *return_value)
{
u8 local0;
u8 local1;
acpi_status status;
/* High byte */
status = acpi_db_hex_char_to_value(hex_byte[0], &local0);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Low byte */
status = acpi_db_hex_char_to_value(hex_byte[1], &local1);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = (u8)((local0 << 4) | local1);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_convert_to_buffer
*
* PARAMETERS: string - Input string to be converted
* object - Where the buffer object is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert a string to a buffer object. String is treated a list
* of buffer elements, each separated by a space or comma.
*
******************************************************************************/
static acpi_status
acpi_db_convert_to_buffer(char *string, union acpi_object *object)
{
u32 i;
u32 j;
u32 length;
u8 *buffer;
acpi_status status;
/* Generate the final buffer length */
for (i = 0, length = 0; string[i];) {
i += 2;
length++;
while (string[i] && ((string[i] == ',') || (string[i] == ' '))) {
i++;
}
}
buffer = ACPI_ALLOCATE(length);
if (!buffer) {
return (AE_NO_MEMORY);
}
/* Convert the command line bytes to the buffer */
for (i = 0, j = 0; string[i];) {
status = acpi_db_hex_byte_to_binary(&string[i], &buffer[j]);
if (ACPI_FAILURE(status)) {
ACPI_FREE(buffer);
return (status);
}
j++;
i += 2;
while (string[i] && ((string[i] == ',') || (string[i] == ' '))) {
i++;
}
}
object->type = ACPI_TYPE_BUFFER;
object->buffer.pointer = buffer;
object->buffer.length = length;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_convert_to_package
*
* PARAMETERS: string - Input string to be converted
* object - Where the package object is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert a string to a package object. Handles nested packages
* via recursion with acpi_db_convert_to_object.
*
******************************************************************************/
acpi_status acpi_db_convert_to_package(char *string, union acpi_object * object)
{
char *this;
char *next;
u32 i;
acpi_object_type type;
union acpi_object *elements;
acpi_status status;
elements =
ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS *
sizeof(union acpi_object));
this = string;
for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) {
this = acpi_db_get_next_token(this, &next, &type);
if (!this) {
break;
}
/* Recursive call to convert each package element */
status = acpi_db_convert_to_object(type, this, &elements[i]);
if (ACPI_FAILURE(status)) {
acpi_db_delete_objects(i + 1, elements);
ACPI_FREE(elements);
return (status);
}
this = next;
}
object->type = ACPI_TYPE_PACKAGE;
object->package.count = i;
object->package.elements = elements;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_convert_to_object
*
* PARAMETERS: type - Object type as determined by parser
* string - Input string to be converted
* object - Where the new object is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert a typed and tokenized string to an union acpi_object. Typing:
* 1) String objects were surrounded by quotes.
* 2) Buffer objects were surrounded by parentheses.
* 3) Package objects were surrounded by brackets "[]".
* 4) All standalone tokens are treated as integers.
*
******************************************************************************/
acpi_status
acpi_db_convert_to_object(acpi_object_type type,
char *string, union acpi_object * object)
{
acpi_status status = AE_OK;
switch (type) {
case ACPI_TYPE_STRING:
object->type = ACPI_TYPE_STRING;
object->string.pointer = string;
object->string.length = (u32)strlen(string);
break;
case ACPI_TYPE_BUFFER:
status = acpi_db_convert_to_buffer(string, object);
break;
case ACPI_TYPE_PACKAGE:
status = acpi_db_convert_to_package(string, object);
break;
default:
object->type = ACPI_TYPE_INTEGER;
status = acpi_ut_strtoul64(string, 16, &object->integer.value);
break;
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_encode_pld_buffer
*
* PARAMETERS: pld_info - _PLD buffer struct (Using local struct)
*
* RETURN: Encode _PLD buffer suitable for return value from _PLD
*
* DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
*
******************************************************************************/
u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info)
{
u32 *buffer;
u32 dword;
buffer = ACPI_ALLOCATE_ZEROED(ACPI_PLD_BUFFER_SIZE);
if (!buffer) {
return (NULL);
}
/* First 32 bits */
dword = 0;
ACPI_PLD_SET_REVISION(&dword, pld_info->revision);
ACPI_PLD_SET_IGNORE_COLOR(&dword, pld_info->ignore_color);
ACPI_PLD_SET_RED(&dword, pld_info->red);
ACPI_PLD_SET_GREEN(&dword, pld_info->green);
ACPI_PLD_SET_BLUE(&dword, pld_info->blue);
ACPI_MOVE_32_TO_32(&buffer[0], &dword);
/* Second 32 bits */
dword = 0;
ACPI_PLD_SET_WIDTH(&dword, pld_info->width);
ACPI_PLD_SET_HEIGHT(&dword, pld_info->height);
ACPI_MOVE_32_TO_32(&buffer[1], &dword);
/* Third 32 bits */
dword = 0;
ACPI_PLD_SET_USER_VISIBLE(&dword, pld_info->user_visible);
ACPI_PLD_SET_DOCK(&dword, pld_info->dock);
ACPI_PLD_SET_LID(&dword, pld_info->lid);
ACPI_PLD_SET_PANEL(&dword, pld_info->panel);
ACPI_PLD_SET_VERTICAL(&dword, pld_info->vertical_position);
ACPI_PLD_SET_HORIZONTAL(&dword, pld_info->horizontal_position);
ACPI_PLD_SET_SHAPE(&dword, pld_info->shape);
ACPI_PLD_SET_ORIENTATION(&dword, pld_info->group_orientation);
ACPI_PLD_SET_TOKEN(&dword, pld_info->group_token);
ACPI_PLD_SET_POSITION(&dword, pld_info->group_position);
ACPI_PLD_SET_BAY(&dword, pld_info->bay);
ACPI_MOVE_32_TO_32(&buffer[2], &dword);
/* Fourth 32 bits */
dword = 0;
ACPI_PLD_SET_EJECTABLE(&dword, pld_info->ejectable);
ACPI_PLD_SET_OSPM_EJECT(&dword, pld_info->ospm_eject_required);
ACPI_PLD_SET_CABINET(&dword, pld_info->cabinet_number);
ACPI_PLD_SET_CARD_CAGE(&dword, pld_info->card_cage_number);
ACPI_PLD_SET_REFERENCE(&dword, pld_info->reference);
ACPI_PLD_SET_ROTATION(&dword, pld_info->rotation);
ACPI_PLD_SET_ORDER(&dword, pld_info->order);
ACPI_MOVE_32_TO_32(&buffer[3], &dword);
if (pld_info->revision >= 2) {
/* Fifth 32 bits */
dword = 0;
ACPI_PLD_SET_VERT_OFFSET(&dword, pld_info->vertical_offset);
ACPI_PLD_SET_HORIZ_OFFSET(&dword, pld_info->horizontal_offset);
ACPI_MOVE_32_TO_32(&buffer[4], &dword);
}
return (ACPI_CAST_PTR(u8, buffer));
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_pld_buffer
*
* PARAMETERS: obj_desc - Object returned from _PLD method
*
* RETURN: None.
*
* DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
*
******************************************************************************/
#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
void acpi_db_dump_pld_buffer(union acpi_object *obj_desc)
{
union acpi_object *buffer_desc;
struct acpi_pld_info *pld_info;
u8 *new_buffer;
acpi_status status;
/* Object must be of type Package with at least one Buffer element */
if (obj_desc->type != ACPI_TYPE_PACKAGE) {
return;
}
buffer_desc = &obj_desc->package.elements[0];
if (buffer_desc->type != ACPI_TYPE_BUFFER) {
return;
}
/* Convert _PLD buffer to local _PLD struct */
status = acpi_decode_pld_buffer(buffer_desc->buffer.pointer,
buffer_desc->buffer.length, &pld_info);
if (ACPI_FAILURE(status)) {
return;
}
/* Encode local _PLD struct back to a _PLD buffer */
new_buffer = acpi_db_encode_pld_buffer(pld_info);
if (!new_buffer) {
return;
}
/* The two bit-packed buffers should match */
if (memcmp(new_buffer, buffer_desc->buffer.pointer,
buffer_desc->buffer.length)) {
acpi_os_printf
("Converted _PLD buffer does not compare. New:\n");
acpi_ut_dump_buffer(new_buffer,
buffer_desc->buffer.length, DB_BYTE_DISPLAY,
0);
}
/* First 32-bit dword */
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Revision", pld_info->revision);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_IgnoreColor",
pld_info->ignore_color);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Red", pld_info->red);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Green", pld_info->green);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Blue", pld_info->blue);
/* Second 32-bit dword */
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Width", pld_info->width);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Height", pld_info->height);
/* Third 32-bit dword */
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_UserVisible",
pld_info->user_visible);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Dock", pld_info->dock);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Lid", pld_info->lid);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Panel", pld_info->panel);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalPosition",
pld_info->vertical_position);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalPosition",
pld_info->horizontal_position);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Shape", pld_info->shape);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupOrientation",
pld_info->group_orientation);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupToken",
pld_info->group_token);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupPosition",
pld_info->group_position);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Bay", pld_info->bay);
/* Fourth 32-bit dword */
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Ejectable", pld_info->ejectable);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_EjectRequired",
pld_info->ospm_eject_required);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CabinetNumber",
pld_info->cabinet_number);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CardCageNumber",
pld_info->card_cage_number);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Reference", pld_info->reference);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Rotation", pld_info->rotation);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Order", pld_info->order);
/* Fifth 32-bit dword */
if (buffer_desc->buffer.length > 16) {
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalOffset",
pld_info->vertical_offset);
acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalOffset",
pld_info->horizontal_offset);
}
ACPI_FREE(pld_info);
ACPI_FREE(new_buffer);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,764 +0,0 @@
/*******************************************************************************
*
* Module Name: dbexec - debugger control method execution
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdebug.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbexec")
static struct acpi_db_method_info acpi_gbl_db_method_info;
/* Local prototypes */
static acpi_status
acpi_db_execute_method(struct acpi_db_method_info *info,
struct acpi_buffer *return_obj);
static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
static u32 acpi_db_get_outstanding_allocations(void);
static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
static acpi_status
acpi_db_execution_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value);
/*******************************************************************************
*
* FUNCTION: acpi_db_delete_objects
*
* PARAMETERS: count - Count of objects in the list
* objects - Array of ACPI_OBJECTs to be deleted
*
* RETURN: None
*
* DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
* packages via recursion.
*
******************************************************************************/
void acpi_db_delete_objects(u32 count, union acpi_object *objects)
{
u32 i;
for (i = 0; i < count; i++) {
switch (objects[i].type) {
case ACPI_TYPE_BUFFER:
ACPI_FREE(objects[i].buffer.pointer);
break;
case ACPI_TYPE_PACKAGE:
/* Recursive call to delete package elements */
acpi_db_delete_objects(objects[i].package.count,
objects[i].package.elements);
/* Free the elements array */
ACPI_FREE(objects[i].package.elements);
break;
default:
break;
}
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_execute_method
*
* PARAMETERS: info - Valid info segment
* return_obj - Where to put return object
*
* RETURN: Status
*
* DESCRIPTION: Execute a control method.
*
******************************************************************************/
static acpi_status
acpi_db_execute_method(struct acpi_db_method_info *info,
struct acpi_buffer *return_obj)
{
acpi_status status;
struct acpi_object_list param_objects;
union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
u32 i;
ACPI_FUNCTION_TRACE(db_execute_method);
if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
acpi_os_printf("Warning: debug output is not enabled!\n");
}
param_objects.count = 0;
param_objects.pointer = NULL;
/* Pass through any command-line arguments */
if (info->args && info->args[0]) {
/* Get arguments passed on the command line */
for (i = 0; (info->args[i] && *(info->args[i])); i++) {
/* Convert input string (token) to an actual union acpi_object */
status = acpi_db_convert_to_object(info->types[i],
info->args[i],
&params[i]);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While parsing method arguments"));
goto cleanup;
}
}
param_objects.count = i;
param_objects.pointer = params;
}
/* Prepare for a return object of arbitrary size */
return_obj->pointer = acpi_gbl_db_buffer;
return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
/* Do the actual method execution */
acpi_gbl_method_executing = TRUE;
status = acpi_evaluate_object(NULL, info->pathname,
&param_objects, return_obj);
acpi_gbl_cm_single_step = FALSE;
acpi_gbl_method_executing = FALSE;
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"while executing %s from debugger",
info->pathname));
if (status == AE_BUFFER_OVERFLOW) {
ACPI_ERROR((AE_INFO,
"Possible overflow of internal debugger "
"buffer (size 0x%X needed 0x%X)",
ACPI_DEBUG_BUFFER_SIZE,
(u32)return_obj->length));
}
}
cleanup:
acpi_db_delete_objects(param_objects.count, params);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_execute_setup
*
* PARAMETERS: info - Valid method info
*
* RETURN: None
*
* DESCRIPTION: Setup info segment prior to method execution
*
******************************************************************************/
static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
{
acpi_status status;
ACPI_FUNCTION_NAME(db_execute_setup);
/* Catenate the current scope to the supplied name */
info->pathname[0] = 0;
if ((info->name[0] != '\\') && (info->name[0] != '/')) {
if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
acpi_gbl_db_scope_buf)) {
status = AE_BUFFER_OVERFLOW;
goto error_exit;
}
}
if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
info->name)) {
status = AE_BUFFER_OVERFLOW;
goto error_exit;
}
acpi_db_prep_namestring(info->pathname);
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf("Evaluating %s\n", info->pathname);
if (info->flags & EX_SINGLE_STEP) {
acpi_gbl_cm_single_step = TRUE;
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
}
else {
/* No single step, allow redirection to a file */
acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
}
return (AE_OK);
error_exit:
ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
return (status);
}
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
{
return (cache->total_allocated - cache->total_freed -
cache->current_depth);
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_db_get_outstanding_allocations
*
* PARAMETERS: None
*
* RETURN: Current global allocation count minus cache entries
*
* DESCRIPTION: Determine the current number of "outstanding" allocations --
* those allocations that have not been freed and also are not
* in one of the various object caches.
*
******************************************************************************/
static u32 acpi_db_get_outstanding_allocations(void)
{
u32 outstanding = 0;
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
#endif
return (outstanding);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_execution_walk
*
* PARAMETERS: WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Execute a control method. Name is relative to the current
* scope.
*
******************************************************************************/
static acpi_status
acpi_db_execution_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value)
{
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
struct acpi_buffer return_obj;
acpi_status status;
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc->method.param_count) {
return (AE_OK);
}
return_obj.pointer = NULL;
return_obj.length = ACPI_ALLOCATE_BUFFER;
acpi_ns_print_node_pathname(node, "Evaluating");
/* Do the actual method execution */
acpi_os_printf("\n");
acpi_gbl_method_executing = TRUE;
status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
acpi_ut_get_node_name(node),
acpi_format_exception(status));
acpi_gbl_method_executing = FALSE;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_execute
*
* PARAMETERS: name - Name of method to execute
* args - Parameters to the method
* Types -
* flags - single step/no single step
*
* RETURN: None
*
* DESCRIPTION: Execute a control method. Name is relative to the current
* scope.
*
******************************************************************************/
void
acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags)
{
acpi_status status;
struct acpi_buffer return_obj;
char *name_string;
#ifdef ACPI_DEBUG_OUTPUT
u32 previous_allocations;
u32 allocations;
#endif
/*
* Allow one execution to be performed by debugger or single step
* execution will be dead locked by the interpreter mutexes.
*/
if (acpi_gbl_method_executing) {
acpi_os_printf("Only one debugger execution is allowed.\n");
return;
}
#ifdef ACPI_DEBUG_OUTPUT
/* Memory allocation tracking */
previous_allocations = acpi_db_get_outstanding_allocations();
#endif
if (*name == '*') {
(void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
acpi_db_execution_walk, NULL, NULL,
NULL);
return;
} else {
name_string = ACPI_ALLOCATE(strlen(name) + 1);
if (!name_string) {
return;
}
memset(&acpi_gbl_db_method_info, 0,
sizeof(struct acpi_db_method_info));
strcpy(name_string, name);
acpi_ut_strupr(name_string);
acpi_gbl_db_method_info.name = name_string;
acpi_gbl_db_method_info.args = args;
acpi_gbl_db_method_info.types = types;
acpi_gbl_db_method_info.flags = flags;
return_obj.pointer = NULL;
return_obj.length = ACPI_ALLOCATE_BUFFER;
status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
if (ACPI_FAILURE(status)) {
ACPI_FREE(name_string);
return;
}
/* Get the NS node, determines existence also */
status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
&acpi_gbl_db_method_info.method);
if (ACPI_SUCCESS(status)) {
status =
acpi_db_execute_method(&acpi_gbl_db_method_info,
&return_obj);
}
ACPI_FREE(name_string);
}
/*
* Allow any handlers in separate threads to complete.
* (Such as Notify handlers invoked from AML executed above).
*/
acpi_os_sleep((u64)10);
#ifdef ACPI_DEBUG_OUTPUT
/* Memory allocation tracking */
allocations =
acpi_db_get_outstanding_allocations() - previous_allocations;
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
if (allocations > 0) {
acpi_os_printf
("0x%X Outstanding allocations after evaluation of %s\n",
allocations, acpi_gbl_db_method_info.pathname);
}
#endif
if (ACPI_FAILURE(status)) {
acpi_os_printf("Evaluation of %s failed with status %s\n",
acpi_gbl_db_method_info.pathname,
acpi_format_exception(status));
} else {
/* Display a return object, if any */
if (return_obj.length) {
acpi_os_printf("Evaluation of %s returned object %p, "
"external buffer length %X\n",
acpi_gbl_db_method_info.pathname,
return_obj.pointer,
(u32)return_obj.length);
acpi_db_dump_external_object(return_obj.pointer, 1);
/* Dump a _PLD buffer if present */
if (ACPI_COMPARE_NAME
((ACPI_CAST_PTR
(struct acpi_namespace_node,
acpi_gbl_db_method_info.method)->name.ascii),
METHOD_NAME__PLD)) {
acpi_db_dump_pld_buffer(return_obj.pointer);
}
} else {
acpi_os_printf
("No object was returned from evaluation of %s\n",
acpi_gbl_db_method_info.pathname);
}
}
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_method_thread
*
* PARAMETERS: context - Execution info segment
*
* RETURN: None
*
* DESCRIPTION: Debugger execute thread. Waits for a command line, then
* simply dispatches it.
*
******************************************************************************/
static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
{
acpi_status status;
struct acpi_db_method_info *info = context;
struct acpi_db_method_info local_info;
u32 i;
u8 allow;
struct acpi_buffer return_obj;
/*
* acpi_gbl_db_method_info.Arguments will be passed as method arguments.
* Prevent acpi_gbl_db_method_info from being modified by multiple threads
* concurrently.
*
* Note: The arguments we are passing are used by the ASL test suite
* (aslts). Do not change them without updating the tests.
*/
(void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
if (info->init_args) {
acpi_db_uint32_to_hex_string(info->num_created,
info->index_of_thread_str);
acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
info->id_of_thread_str);
}
if (info->threads && (info->num_created < info->num_threads)) {
info->threads[info->num_created++] = acpi_os_get_thread_id();
}
local_info = *info;
local_info.args = local_info.arguments;
local_info.arguments[0] = local_info.num_threads_str;
local_info.arguments[1] = local_info.id_of_thread_str;
local_info.arguments[2] = local_info.index_of_thread_str;
local_info.arguments[3] = NULL;
local_info.types = local_info.arg_types;
(void)acpi_os_signal_semaphore(info->info_gate, 1);
for (i = 0; i < info->num_loops; i++) {
status = acpi_db_execute_method(&local_info, &return_obj);
if (ACPI_FAILURE(status)) {
acpi_os_printf
("%s During evaluation of %s at iteration %X\n",
acpi_format_exception(status), info->pathname, i);
if (status == AE_ABORT_METHOD) {
break;
}
}
#if 0
if ((i % 100) == 0) {
acpi_os_printf("%u loops, Thread 0x%x\n",
i, acpi_os_get_thread_id());
}
if (return_obj.length) {
acpi_os_printf
("Evaluation of %s returned object %p Buflen %X\n",
info->pathname, return_obj.pointer,
(u32)return_obj.length);
acpi_db_dump_external_object(return_obj.pointer, 1);
}
#endif
}
/* Signal our completion */
allow = 0;
(void)acpi_os_wait_semaphore(info->thread_complete_gate,
1, ACPI_WAIT_FOREVER);
info->num_completed++;
if (info->num_completed == info->num_threads) {
/* Do signal for main thread once only */
allow = 1;
}
(void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
if (allow) {
status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
if (ACPI_FAILURE(status)) {
acpi_os_printf
("Could not signal debugger thread sync semaphore, %s\n",
acpi_format_exception(status));
}
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_create_execution_threads
*
* PARAMETERS: num_threads_arg - Number of threads to create
* num_loops_arg - Loop count for the thread(s)
* method_name_arg - Control method to execute
*
* RETURN: None
*
* DESCRIPTION: Create threads to execute method(s)
*
******************************************************************************/
void
acpi_db_create_execution_threads(char *num_threads_arg,
char *num_loops_arg, char *method_name_arg)
{
acpi_status status;
u32 num_threads;
u32 num_loops;
u32 i;
u32 size;
acpi_mutex main_thread_gate;
acpi_mutex thread_complete_gate;
acpi_mutex info_gate;
/* Get the arguments */
num_threads = strtoul(num_threads_arg, NULL, 0);
num_loops = strtoul(num_loops_arg, NULL, 0);
if (!num_threads || !num_loops) {
acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
num_threads, num_loops);
return;
}
/*
* Create the semaphore for synchronization of
* the created threads with the main thread.
*/
status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not create semaphore for "
"synchronization with the main thread, %s\n",
acpi_format_exception(status));
return;
}
/*
* Create the semaphore for synchronization
* between the created threads.
*/
status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not create semaphore for "
"synchronization between the created threads, %s\n",
acpi_format_exception(status));
(void)acpi_os_delete_semaphore(main_thread_gate);
return;
}
status = acpi_os_create_semaphore(1, 1, &info_gate);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not create semaphore for "
"synchronization of AcpiGbl_DbMethodInfo, %s\n",
acpi_format_exception(status));
(void)acpi_os_delete_semaphore(thread_complete_gate);
(void)acpi_os_delete_semaphore(main_thread_gate);
return;
}
memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
/* Array to store IDs of threads */
acpi_gbl_db_method_info.num_threads = num_threads;
size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
if (acpi_gbl_db_method_info.threads == NULL) {
acpi_os_printf("No memory for thread IDs array\n");
(void)acpi_os_delete_semaphore(main_thread_gate);
(void)acpi_os_delete_semaphore(thread_complete_gate);
(void)acpi_os_delete_semaphore(info_gate);
return;
}
memset(acpi_gbl_db_method_info.threads, 0, size);
/* Setup the context to be passed to each thread */
acpi_gbl_db_method_info.name = method_name_arg;
acpi_gbl_db_method_info.flags = 0;
acpi_gbl_db_method_info.num_loops = num_loops;
acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
acpi_gbl_db_method_info.info_gate = info_gate;
/* Init arguments to be passed to method */
acpi_gbl_db_method_info.init_args = 1;
acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
acpi_gbl_db_method_info.arguments[0] =
acpi_gbl_db_method_info.num_threads_str;
acpi_gbl_db_method_info.arguments[1] =
acpi_gbl_db_method_info.id_of_thread_str;
acpi_gbl_db_method_info.arguments[2] =
acpi_gbl_db_method_info.index_of_thread_str;
acpi_gbl_db_method_info.arguments[3] = NULL;
acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
acpi_db_uint32_to_hex_string(num_threads,
acpi_gbl_db_method_info.num_threads_str);
status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
if (ACPI_FAILURE(status)) {
goto cleanup_and_exit;
}
/* Get the NS node, determines existence also */
status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
&acpi_gbl_db_method_info.method);
if (ACPI_FAILURE(status)) {
acpi_os_printf("%s Could not get handle for %s\n",
acpi_format_exception(status),
acpi_gbl_db_method_info.pathname);
goto cleanup_and_exit;
}
/* Create the threads */
acpi_os_printf("Creating %X threads to execute %X times each\n",
num_threads, num_loops);
for (i = 0; i < (num_threads); i++) {
status =
acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
acpi_db_method_thread,
&acpi_gbl_db_method_info);
if (ACPI_FAILURE(status)) {
break;
}
}
/* Wait for all threads to complete */
(void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf("All threads (%X) have completed\n", num_threads);
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
cleanup_and_exit:
/* Cleanup and exit */
(void)acpi_os_delete_semaphore(main_thread_gate);
(void)acpi_os_delete_semaphore(thread_complete_gate);
(void)acpi_os_delete_semaphore(info_gate);
acpi_os_free(acpi_gbl_db_method_info.threads);
acpi_gbl_db_method_info.threads = NULL;
}

View File

@@ -1,256 +0,0 @@
/*******************************************************************************
*
* Module Name: dbfileio - Debugger file I/O commands. These can't usually
* be used when running the debugger in Ring 0 (Kernel mode)
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdebug.h"
#include "actables.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbfileio")
#ifdef ACPI_DEBUGGER
/*******************************************************************************
*
* FUNCTION: acpi_db_close_debug_file
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: If open, close the current debug output file
*
******************************************************************************/
void acpi_db_close_debug_file(void)
{
#ifdef ACPI_APPLICATION
if (acpi_gbl_debug_file) {
fclose(acpi_gbl_debug_file);
acpi_gbl_debug_file = NULL;
acpi_gbl_db_output_to_file = FALSE;
acpi_os_printf("Debug output file %s closed\n",
acpi_gbl_db_debug_filename);
}
#endif
}
/*******************************************************************************
*
* FUNCTION: acpi_db_open_debug_file
*
* PARAMETERS: name - Filename to open
*
* RETURN: None
*
* DESCRIPTION: Open a file where debug output will be directed.
*
******************************************************************************/
void acpi_db_open_debug_file(char *name)
{
#ifdef ACPI_APPLICATION
acpi_db_close_debug_file();
acpi_gbl_debug_file = fopen(name, "w+");
if (!acpi_gbl_debug_file) {
acpi_os_printf("Could not open debug file %s\n", name);
return;
}
acpi_os_printf("Debug output file %s opened\n", name);
strncpy(acpi_gbl_db_debug_filename, name,
sizeof(acpi_gbl_db_debug_filename));
acpi_gbl_db_output_to_file = TRUE;
#endif
}
#endif
#ifdef ACPI_APPLICATION
#include "acapps.h"
/*******************************************************************************
*
* FUNCTION: ae_local_load_table
*
* PARAMETERS: table - pointer to a buffer containing the entire
* table to be loaded
*
* RETURN: Status
*
* DESCRIPTION: This function is called to load a table from the caller's
* buffer. The buffer must contain an entire ACPI Table including
* a valid header. The header fields will be verified, and if it
* is determined that the table is invalid, the call will fail.
*
******************************************************************************/
static acpi_status ae_local_load_table(struct acpi_table_header *table)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ae_local_load_table);
#if 0
/* struct acpi_table_desc table_info; */
if (!table) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
table_info.pointer = table;
status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Install the new table into the local data structures */
status = acpi_tb_init_table_descriptor(&table_info);
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
/* Table already exists, no error */
status = AE_OK;
}
/* Free table allocated by acpi_tb_get_table */
acpi_tb_delete_single_table(&table_info);
return_ACPI_STATUS(status);
}
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
status =
acpi_ns_load_table(table_info.installed_desc, acpi_gbl_root_node);
if (ACPI_FAILURE(status)) {
/* Uninstall table and free the buffer */
acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_DSDT);
return_ACPI_STATUS(status);
}
#endif
#endif
return_ACPI_STATUS(status);
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_db_get_table_from_file
*
* PARAMETERS: filename - File where table is located
* return_table - Where a pointer to the table is returned
*
* RETURN: Status
*
* DESCRIPTION: Load an ACPI table from a file
*
******************************************************************************/
acpi_status
acpi_db_get_table_from_file(char *filename,
struct acpi_table_header **return_table,
u8 must_be_aml_file)
{
#ifdef ACPI_APPLICATION
acpi_status status;
struct acpi_table_header *table;
u8 is_aml_table = TRUE;
status = acpi_ut_read_table_from_file(filename, &table);
if (ACPI_FAILURE(status)) {
return (status);
}
if (must_be_aml_file) {
is_aml_table = acpi_ut_is_aml_table(table);
if (!is_aml_table) {
ACPI_EXCEPTION((AE_INFO, AE_OK,
"Input for -e is not an AML table: "
"\"%4.4s\" (must be DSDT/SSDT)",
table->signature));
return (AE_TYPE);
}
}
if (is_aml_table) {
/* Attempt to recognize and install the table */
status = ae_local_load_table(table);
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
acpi_os_printf
("Table %4.4s is already installed\n",
table->signature);
} else {
acpi_os_printf("Could not install table, %s\n",
acpi_format_exception(status));
}
return (status);
}
acpi_tb_print_table_header(0, table);
fprintf(stderr,
"Acpi table [%4.4s] successfully installed and loaded\n",
table->signature);
}
acpi_gbl_acpi_hardware_present = FALSE;
if (return_table) {
*return_table = table;
}
#endif /* ACPI_APPLICATION */
return (AE_OK);
}

View File

@@ -1,239 +0,0 @@
/******************************************************************************
*
* Module Name: dbhistry - debugger HISTORY command
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbhistry")
#define HI_NO_HISTORY 0
#define HI_RECORD_HISTORY 1
#define HISTORY_SIZE 40
typedef struct history_info {
char *command;
u32 cmd_num;
} HISTORY_INFO;
static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE];
static u16 acpi_gbl_lo_history = 0;
static u16 acpi_gbl_num_history = 0;
static u16 acpi_gbl_next_history_index = 0;
u32 acpi_gbl_next_cmd_num = 1;
/*******************************************************************************
*
* FUNCTION: acpi_db_add_to_history
*
* PARAMETERS: command_line - Command to add
*
* RETURN: None
*
* DESCRIPTION: Add a command line to the history buffer.
*
******************************************************************************/
void acpi_db_add_to_history(char *command_line)
{
u16 cmd_len;
u16 buffer_len;
/* Put command into the next available slot */
cmd_len = (u16)strlen(command_line);
if (!cmd_len) {
return;
}
if (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command !=
NULL) {
buffer_len =
(u16)
strlen(acpi_gbl_history_buffer[acpi_gbl_next_history_index].
command);
if (cmd_len > buffer_len) {
acpi_os_free(acpi_gbl_history_buffer
[acpi_gbl_next_history_index].command);
acpi_gbl_history_buffer[acpi_gbl_next_history_index].
command = acpi_os_allocate(cmd_len + 1);
}
} else {
acpi_gbl_history_buffer[acpi_gbl_next_history_index].command =
acpi_os_allocate(cmd_len + 1);
}
strcpy(acpi_gbl_history_buffer[acpi_gbl_next_history_index].command,
command_line);
acpi_gbl_history_buffer[acpi_gbl_next_history_index].cmd_num =
acpi_gbl_next_cmd_num;
/* Adjust indexes */
if ((acpi_gbl_num_history == HISTORY_SIZE) &&
(acpi_gbl_next_history_index == acpi_gbl_lo_history)) {
acpi_gbl_lo_history++;
if (acpi_gbl_lo_history >= HISTORY_SIZE) {
acpi_gbl_lo_history = 0;
}
}
acpi_gbl_next_history_index++;
if (acpi_gbl_next_history_index >= HISTORY_SIZE) {
acpi_gbl_next_history_index = 0;
}
acpi_gbl_next_cmd_num++;
if (acpi_gbl_num_history < HISTORY_SIZE) {
acpi_gbl_num_history++;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_display_history
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Display the contents of the history buffer
*
******************************************************************************/
void acpi_db_display_history(void)
{
u32 i;
u16 history_index;
history_index = acpi_gbl_lo_history;
/* Dump entire history buffer */
for (i = 0; i < acpi_gbl_num_history; i++) {
if (acpi_gbl_history_buffer[history_index].command) {
acpi_os_printf("%3ld %s\n",
acpi_gbl_history_buffer[history_index].
cmd_num,
acpi_gbl_history_buffer[history_index].
command);
}
history_index++;
if (history_index >= HISTORY_SIZE) {
history_index = 0;
}
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_get_from_history
*
* PARAMETERS: command_num_arg - String containing the number of the
* command to be retrieved
*
* RETURN: Pointer to the retrieved command. Null on error.
*
* DESCRIPTION: Get a command from the history buffer
*
******************************************************************************/
char *acpi_db_get_from_history(char *command_num_arg)
{
u32 cmd_num;
if (command_num_arg == NULL) {
cmd_num = acpi_gbl_next_cmd_num - 1;
}
else {
cmd_num = strtoul(command_num_arg, NULL, 0);
}
return (acpi_db_get_history_by_index(cmd_num));
}
/*******************************************************************************
*
* FUNCTION: acpi_db_get_history_by_index
*
* PARAMETERS: cmd_num - Index of the desired history entry.
* Values are 0...(acpi_gbl_next_cmd_num - 1)
*
* RETURN: Pointer to the retrieved command. Null on error.
*
* DESCRIPTION: Get a command from the history buffer
*
******************************************************************************/
char *acpi_db_get_history_by_index(u32 cmd_num)
{
u32 i;
u16 history_index;
/* Search history buffer */
history_index = acpi_gbl_lo_history;
for (i = 0; i < acpi_gbl_num_history; i++) {
if (acpi_gbl_history_buffer[history_index].cmd_num == cmd_num) {
/* Found the command, return it */
return (acpi_gbl_history_buffer[history_index].command);
}
/* History buffer is circular */
history_index++;
if (history_index >= HISTORY_SIZE) {
history_index = 0;
}
}
acpi_os_printf("Invalid history number: %u\n", history_index);
return (NULL);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,369 +0,0 @@
/*******************************************************************************
*
* Module Name: dbmethod - Debug commands for control methods
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acnamesp.h"
#include "acdebug.h"
#include "acparser.h"
#include "acpredef.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbmethod")
/*******************************************************************************
*
* FUNCTION: acpi_db_set_method_breakpoint
*
* PARAMETERS: location - AML offset of breakpoint
* walk_state - Current walk info
* op - Current Op (from parse walk)
*
* RETURN: None
*
* DESCRIPTION: Set a breakpoint in a control method at the specified
* AML offset
*
******************************************************************************/
void
acpi_db_set_method_breakpoint(char *location,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
u32 address;
u32 aml_offset;
if (!op) {
acpi_os_printf("There is no method currently executing\n");
return;
}
/* Get and verify the breakpoint address */
address = strtoul(location, NULL, 16);
aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
walk_state->parser_state.aml_start);
if (address <= aml_offset) {
acpi_os_printf("Breakpoint %X is beyond current address %X\n",
address, aml_offset);
}
/* Save breakpoint in current walk */
walk_state->user_breakpoint = address;
acpi_os_printf("Breakpoint set at AML offset %X\n", address);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_set_method_call_breakpoint
*
* PARAMETERS: op - Current Op (from parse walk)
*
* RETURN: None
*
* DESCRIPTION: Set a breakpoint in a control method at the specified
* AML offset
*
******************************************************************************/
void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op)
{
if (!op) {
acpi_os_printf("There is no method currently executing\n");
return;
}
acpi_gbl_step_to_next_call = TRUE;
}
/*******************************************************************************
*
* FUNCTION: acpi_db_set_method_data
*
* PARAMETERS: type_arg - L for local, A for argument
* index_arg - which one
* value_arg - Value to set.
*
* RETURN: None
*
* DESCRIPTION: Set a local or argument for the running control method.
* NOTE: only object supported is Number.
*
******************************************************************************/
void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg)
{
char type;
u32 index;
u32 value;
struct acpi_walk_state *walk_state;
union acpi_operand_object *obj_desc;
acpi_status status;
struct acpi_namespace_node *node;
/* Validate type_arg */
acpi_ut_strupr(type_arg);
type = type_arg[0];
if ((type != 'L') && (type != 'A') && (type != 'N')) {
acpi_os_printf("Invalid SET operand: %s\n", type_arg);
return;
}
value = strtoul(value_arg, NULL, 16);
if (type == 'N') {
node = acpi_db_convert_to_node(index_arg);
if (!node) {
return;
}
if (node->type != ACPI_TYPE_INTEGER) {
acpi_os_printf("Can only set Integer nodes\n");
return;
}
obj_desc = node->object;
obj_desc->integer.value = value;
return;
}
/* Get the index and value */
index = strtoul(index_arg, NULL, 16);
walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
if (!walk_state) {
acpi_os_printf("There is no method currently executing\n");
return;
}
/* Create and initialize the new object */
obj_desc = acpi_ut_create_integer_object((u64)value);
if (!obj_desc) {
acpi_os_printf("Could not create an internal object\n");
return;
}
/* Store the new object into the target */
switch (type) {
case 'A':
/* Set a method argument */
if (index > ACPI_METHOD_MAX_ARG) {
acpi_os_printf("Arg%u - Invalid argument name\n",
index);
goto cleanup;
}
status = acpi_ds_store_object_to_local(ACPI_REFCLASS_ARG,
index, obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
obj_desc = walk_state->arguments[index].object;
acpi_os_printf("Arg%u: ", index);
acpi_db_display_internal_object(obj_desc, walk_state);
break;
case 'L':
/* Set a method local */
if (index > ACPI_METHOD_MAX_LOCAL) {
acpi_os_printf
("Local%u - Invalid local variable name\n", index);
goto cleanup;
}
status = acpi_ds_store_object_to_local(ACPI_REFCLASS_LOCAL,
index, obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
obj_desc = walk_state->local_variables[index].object;
acpi_os_printf("Local%u: ", index);
acpi_db_display_internal_object(obj_desc, walk_state);
break;
default:
break;
}
cleanup:
acpi_ut_remove_reference(obj_desc);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_disassemble_aml
*
* PARAMETERS: statements - Number of statements to disassemble
* op - Current Op (from parse walk)
*
* RETURN: None
*
* DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
* of statements specified.
*
******************************************************************************/
void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op)
{
u32 num_statements = 8;
if (!op) {
acpi_os_printf("There is no method currently executing\n");
return;
}
if (statements) {
num_statements = strtoul(statements, NULL, 0);
}
#ifdef ACPI_DISASSEMBLER
acpi_dm_disassemble(NULL, op, num_statements);
#endif
}
/*******************************************************************************
*
* FUNCTION: acpi_db_disassemble_method
*
* PARAMETERS: name - Name of control method
*
* RETURN: None
*
* DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
* of statements specified.
*
******************************************************************************/
acpi_status acpi_db_disassemble_method(char *name)
{
acpi_status status;
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *method;
method = acpi_db_convert_to_node(name);
if (!method) {
return (AE_BAD_PARAMETER);
}
if (method->type != ACPI_TYPE_METHOD) {
ACPI_ERROR((AE_INFO, "%s (%s): Object must be a control method",
name, acpi_ut_get_type_name(method->type)));
return (AE_BAD_PARAMETER);
}
obj_desc = method->object;
op = acpi_ps_create_scope_op(obj_desc->method.aml_start);
if (!op) {
return (AE_NO_MEMORY);
}
/* Create and initialize a new walk state */
walk_state = acpi_ds_create_walk_state(0, op, NULL, NULL);
if (!walk_state) {
return (AE_NO_MEMORY);
}
status = acpi_ds_init_aml_walk(walk_state, op, NULL,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL,
ACPI_IMODE_LOAD_PASS1);
if (ACPI_FAILURE(status)) {
return (status);
}
status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
walk_state->owner_id = obj_desc->method.owner_id;
/* Push start scope on scope stack and make it current */
status = acpi_ds_scope_stack_push(method, method->type, walk_state);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Parse the entire method AML including deferred operators */
walk_state->parse_flags &= ~ACPI_PARSE_DELETE_TREE;
walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE;
status = acpi_ps_parse_aml(walk_state);
#ifdef ACPI_DISASSEMBLER
(void)acpi_dm_parse_deferred_ops(op);
/* Now we can disassemble the method */
acpi_gbl_dm_opt_verbose = FALSE;
acpi_dm_disassemble(NULL, op, 0);
acpi_gbl_dm_opt_verbose = TRUE;
#endif
acpi_ps_delete_parse_tree(op);
/* Method cleanup */
acpi_ns_delete_namespace_subtree(method);
acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
acpi_ut_release_owner_id(&obj_desc->method.owner_id);
return (AE_OK);
}

View File

@@ -1,947 +0,0 @@
/*******************************************************************************
*
* Module Name: dbnames - Debugger commands for the acpi namespace
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acdebug.h"
#include "acpredef.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbnames")
/* Local prototypes */
static acpi_status
acpi_db_walk_and_match_name(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
static acpi_status
acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
static acpi_status
acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
static acpi_status
acpi_db_walk_for_object_counts(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
static acpi_status
acpi_db_integrity_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value);
static acpi_status
acpi_db_walk_for_references(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
static acpi_status
acpi_db_bus_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value);
/*
* Arguments for the Objects command
* These object types map directly to the ACPI_TYPES
*/
static struct acpi_db_argument_info acpi_db_object_types[] = {
{"ANY"},
{"INTEGERS"},
{"STRINGS"},
{"BUFFERS"},
{"PACKAGES"},
{"FIELDS"},
{"DEVICES"},
{"EVENTS"},
{"METHODS"},
{"MUTEXES"},
{"REGIONS"},
{"POWERRESOURCES"},
{"PROCESSORS"},
{"THERMALZONES"},
{"BUFFERFIELDS"},
{"DDBHANDLES"},
{"DEBUG"},
{"REGIONFIELDS"},
{"BANKFIELDS"},
{"INDEXFIELDS"},
{"REFERENCES"},
{"ALIASES"},
{"METHODALIASES"},
{"NOTIFY"},
{"ADDRESSHANDLER"},
{"RESOURCE"},
{"RESOURCEFIELD"},
{"SCOPES"},
{NULL} /* Must be null terminated */
};
/*******************************************************************************
*
* FUNCTION: acpi_db_set_scope
*
* PARAMETERS: name - New scope path
*
* RETURN: Status
*
* DESCRIPTION: Set the "current scope" as maintained by this utility.
* The scope is used as a prefix to ACPI paths.
*
******************************************************************************/
void acpi_db_set_scope(char *name)
{
acpi_status status;
struct acpi_namespace_node *node;
if (!name || name[0] == 0) {
acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf);
return;
}
acpi_db_prep_namestring(name);
if (ACPI_IS_ROOT_PREFIX(name[0])) {
/* Validate new scope from the root */
status = acpi_ns_get_node(acpi_gbl_root_node, name,
ACPI_NS_NO_UPSEARCH, &node);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
acpi_gbl_db_scope_buf[0] = 0;
} else {
/* Validate new scope relative to old scope */
status = acpi_ns_get_node(acpi_gbl_db_scope_node, name,
ACPI_NS_NO_UPSEARCH, &node);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
}
/* Build the final pathname */
if (acpi_ut_safe_strcat
(acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) {
status = AE_BUFFER_OVERFLOW;
goto error_exit;
}
if (acpi_ut_safe_strcat
(acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) {
status = AE_BUFFER_OVERFLOW;
goto error_exit;
}
acpi_gbl_db_scope_node = node;
acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf);
return;
error_exit:
acpi_os_printf("Could not attach scope: %s, %s\n",
name, acpi_format_exception(status));
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_namespace
*
* PARAMETERS: start_arg - Node to begin namespace dump
* depth_arg - Maximum tree depth to be dumped
*
* RETURN: None
*
* DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed
* with type and other information.
*
******************************************************************************/
void acpi_db_dump_namespace(char *start_arg, char *depth_arg)
{
acpi_handle subtree_entry = acpi_gbl_root_node;
u32 max_depth = ACPI_UINT32_MAX;
/* No argument given, just start at the root and dump entire namespace */
if (start_arg) {
subtree_entry = acpi_db_convert_to_node(start_arg);
if (!subtree_entry) {
return;
}
/* Now we can check for the depth argument */
if (depth_arg) {
max_depth = strtoul(depth_arg, NULL, 0);
}
}
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n",
((struct acpi_namespace_node *)subtree_entry)->name.
ascii, subtree_entry);
/* Display the subtree */
acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
ACPI_OWNER_ID_MAX, subtree_entry);
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_namespace_paths
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Dump entire namespace with full object pathnames and object
* type information. Alternative to "namespace" command.
*
******************************************************************************/
void acpi_db_dump_namespace_paths(void)
{
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf("ACPI Namespace (from root):\n");
/* Display the entire namespace */
acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY,
ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX,
acpi_gbl_root_node);
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_namespace_by_owner
*
* PARAMETERS: owner_arg - Owner ID whose nodes will be displayed
* depth_arg - Maximum tree depth to be dumped
*
* RETURN: None
*
* DESCRIPTION: Dump elements of the namespace that are owned by the owner_id.
*
******************************************************************************/
void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg)
{
acpi_handle subtree_entry = acpi_gbl_root_node;
u32 max_depth = ACPI_UINT32_MAX;
acpi_owner_id owner_id;
owner_id = (acpi_owner_id) strtoul(owner_arg, NULL, 0);
/* Now we can check for the depth argument */
if (depth_arg) {
max_depth = strtoul(depth_arg, NULL, 0);
}
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id);
/* Display the subtree */
acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
owner_id, subtree_entry);
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_walk_and_match_name
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Find a particular name/names within the namespace. Wildcards
* are supported -- '?' matches any character.
*
******************************************************************************/
static acpi_status
acpi_db_walk_and_match_name(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
acpi_status status;
char *requested_name = (char *)context;
u32 i;
struct acpi_buffer buffer;
struct acpi_walk_info info;
/* Check for a name match */
for (i = 0; i < 4; i++) {
/* Wildcard support */
if ((requested_name[i] != '?') &&
(requested_name[i] != ((struct acpi_namespace_node *)
obj_handle)->name.ascii[i])) {
/* No match, just exit */
return (AE_OK);
}
}
/* Get the full pathname to this object */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could Not get pathname for object %p\n",
obj_handle);
} else {
info.owner_id = ACPI_OWNER_ID_MAX;
info.debug_level = ACPI_UINT32_MAX;
info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
acpi_os_printf("%32s", (char *)buffer.pointer);
(void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info,
NULL);
ACPI_FREE(buffer.pointer);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_find_name_in_namespace
*
* PARAMETERS: name_arg - The 4-character ACPI name to find.
* wildcards are supported.
*
* RETURN: None
*
* DESCRIPTION: Search the namespace for a given name (with wildcards)
*
******************************************************************************/
acpi_status acpi_db_find_name_in_namespace(char *name_arg)
{
char acpi_name[5] = "____";
char *acpi_name_ptr = acpi_name;
if (strlen(name_arg) > ACPI_NAME_SIZE) {
acpi_os_printf("Name must be no longer than 4 characters\n");
return (AE_OK);
}
/* Pad out name with underscores as necessary to create a 4-char name */
acpi_ut_strupr(name_arg);
while (*name_arg) {
*acpi_name_ptr = *name_arg;
acpi_name_ptr++;
name_arg++;
}
/* Walk the namespace from the root */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, acpi_db_walk_and_match_name,
NULL, acpi_name, NULL);
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_walk_for_predefined_names
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Detect and display predefined ACPI names (names that start with
* an underscore)
*
******************************************************************************/
static acpi_status
acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
u32 *count = (u32 *)context;
const union acpi_predefined_info *predefined;
const union acpi_predefined_info *package = NULL;
char *pathname;
char string_buffer[48];
predefined = acpi_ut_match_predefined_method(node->name.ascii);
if (!predefined) {
return (AE_OK);
}
pathname = acpi_ns_get_external_pathname(node);
if (!pathname) {
return (AE_OK);
}
/* If method returns a package, the info is in the next table entry */
if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
package = predefined + 1;
}
acpi_ut_get_expected_return_types(string_buffer,
predefined->info.expected_btypes);
acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname,
METHOD_GET_ARG_COUNT(predefined->info.argument_list),
string_buffer);
if (package) {
acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)",
package->ret_info.type,
package->ret_info.object_type1,
package->ret_info.count1);
}
acpi_os_printf("\n");
/* Check that the declared argument count matches the ACPI spec */
acpi_ns_check_acpi_compliance(pathname, node, predefined);
ACPI_FREE(pathname);
(*count)++;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_check_predefined_names
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Validate all predefined names in the namespace
*
******************************************************************************/
void acpi_db_check_predefined_names(void)
{
u32 count = 0;
/* Search all nodes in namespace */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
acpi_db_walk_for_predefined_names, NULL,
(void *)&count, NULL);
acpi_os_printf("Found %u predefined names in the namespace\n", count);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_walk_for_object_counts
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Display short info about objects in the namespace
*
******************************************************************************/
static acpi_status
acpi_db_walk_for_object_counts(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
struct acpi_object_info *info = (struct acpi_object_info *)context;
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
if (node->type > ACPI_TYPE_NS_NODE_MAX) {
acpi_os_printf("[%4.4s]: Unknown object type %X\n",
node->name.ascii, node->type);
} else {
info->types[node->type]++;
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_walk_for_specific_objects
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Display short info about objects in the namespace
*
******************************************************************************/
static acpi_status
acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
struct acpi_walk_info *info = (struct acpi_walk_info *)context;
struct acpi_buffer buffer;
acpi_status status;
info->count++;
/* Get and display the full pathname to this object */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could Not get pathname for object %p\n",
obj_handle);
return (AE_OK);
}
acpi_os_printf("%32s", (char *)buffer.pointer);
ACPI_FREE(buffer.pointer);
/* Dump short info about the object */
(void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_display_objects
*
* PARAMETERS: obj_type_arg - Type of object to display
* display_count_arg - Max depth to display
*
* RETURN: None
*
* DESCRIPTION: Display objects in the namespace of the requested type
*
******************************************************************************/
acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg)
{
struct acpi_walk_info info;
acpi_object_type type;
struct acpi_object_info *object_info;
u32 i;
u32 total_objects = 0;
/* No argument means display summary/count of all object types */
if (!obj_type_arg) {
object_info =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
/* Walk the namespace from the root */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
acpi_db_walk_for_object_counts, NULL,
(void *)object_info, NULL);
acpi_os_printf("\nSummary of namespace objects:\n\n");
for (i = 0; i < ACPI_TOTAL_TYPES; i++) {
acpi_os_printf("%8u %s\n", object_info->types[i],
acpi_ut_get_type_name(i));
total_objects += object_info->types[i];
}
acpi_os_printf("\n%8u Total namespace objects\n\n",
total_objects);
ACPI_FREE(object_info);
return (AE_OK);
}
/* Get the object type */
type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types);
if (type == ACPI_TYPE_NOT_FOUND) {
acpi_os_printf("Invalid or unsupported argument\n");
return (AE_OK);
}
acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
acpi_os_printf
("Objects of type [%s] defined in the current ACPI Namespace:\n",
acpi_ut_get_type_name(type));
acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
info.count = 0;
info.owner_id = ACPI_OWNER_ID_MAX;
info.debug_level = ACPI_UINT32_MAX;
info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
/* Walk the namespace from the root */
(void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
acpi_db_walk_for_specific_objects, NULL,
(void *)&info, NULL);
acpi_os_printf
("\nFound %u objects of type [%s] in the current ACPI Namespace\n",
info.count, acpi_ut_get_type_name(type));
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_integrity_walk
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Examine one NS node for valid values.
*
******************************************************************************/
static acpi_status
acpi_db_integrity_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value)
{
struct acpi_integrity_info *info =
(struct acpi_integrity_info *)context;
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
union acpi_operand_object *object;
u8 alias = TRUE;
info->nodes++;
/* Verify the NS node, and dereference aliases */
while (alias) {
if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
acpi_os_printf
("Invalid Descriptor Type for Node %p [%s] - "
"is %2.2X should be %2.2X\n", node,
acpi_ut_get_descriptor_name(node),
ACPI_GET_DESCRIPTOR_TYPE(node),
ACPI_DESC_TYPE_NAMED);
return (AE_OK);
}
if ((node->type == ACPI_TYPE_LOCAL_ALIAS) ||
(node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
node = (struct acpi_namespace_node *)node->object;
} else {
alias = FALSE;
}
}
if (node->type > ACPI_TYPE_LOCAL_MAX) {
acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n",
node, node->type);
return (AE_OK);
}
if (!acpi_ut_valid_acpi_name(node->name.ascii)) {
acpi_os_printf("Invalid AcpiName for Node %p\n", node);
return (AE_OK);
}
object = acpi_ns_get_attached_object(node);
if (object) {
info->objects++;
if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf
("Invalid Descriptor Type for Object %p [%s]\n",
object, acpi_ut_get_descriptor_name(object));
}
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_check_integrity
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Check entire namespace for data structure integrity
*
******************************************************************************/
void acpi_db_check_integrity(void)
{
struct acpi_integrity_info info = { 0, 0 };
/* Search all nodes in namespace */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL,
(void *)&info, NULL);
acpi_os_printf("Verified %u namespace nodes with %u Objects\n",
info.nodes, info.objects);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_walk_for_references
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Check if this namespace object refers to the target object
* that is passed in as the context value.
*
* Note: Currently doesn't check subobjects within the Node's object
*
******************************************************************************/
static acpi_status
acpi_db_walk_for_references(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
union acpi_operand_object *obj_desc =
(union acpi_operand_object *)context;
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
/* Check for match against the namespace node itself */
if (node == (void *)obj_desc) {
acpi_os_printf("Object is a Node [%4.4s]\n",
acpi_ut_get_node_name(node));
}
/* Check for match against the object attached to the node */
if (acpi_ns_get_attached_object(node) == obj_desc) {
acpi_os_printf("Reference at Node->Object %p [%4.4s]\n",
node, acpi_ut_get_node_name(node));
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_find_references
*
* PARAMETERS: object_arg - String with hex value of the object
*
* RETURN: None
*
* DESCRIPTION: Search namespace for all references to the input object
*
******************************************************************************/
void acpi_db_find_references(char *object_arg)
{
union acpi_operand_object *obj_desc;
acpi_size address;
/* Convert string to object pointer */
address = strtoul(object_arg, NULL, 16);
obj_desc = ACPI_TO_POINTER(address);
/* Search all nodes in namespace */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, acpi_db_walk_for_references,
NULL, (void *)obj_desc, NULL);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_bus_walk
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Display info about device objects that have a corresponding
* _PRT method.
*
******************************************************************************/
static acpi_status
acpi_db_bus_walk(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value)
{
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
acpi_status status;
struct acpi_buffer buffer;
struct acpi_namespace_node *temp_node;
struct acpi_device_info *info;
u32 i;
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR)) {
return (AE_OK);
}
/* Exit if there is no _PRT under this device */
status = acpi_get_handle(node, METHOD_NAME__PRT,
ACPI_CAST_PTR(acpi_handle, &temp_node));
if (ACPI_FAILURE(status)) {
return (AE_OK);
}
/* Get the full path to this device object */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could Not get pathname for object %p\n",
obj_handle);
return (AE_OK);
}
status = acpi_get_object_info(obj_handle, &info);
if (ACPI_FAILURE(status)) {
return (AE_OK);
}
/* Display the full path */
acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type);
ACPI_FREE(buffer.pointer);
if (info->flags & ACPI_PCI_ROOT_BRIDGE) {
acpi_os_printf(" - Is PCI Root Bridge");
}
acpi_os_printf("\n");
/* _PRT info */
acpi_os_printf("_PRT: %p\n", temp_node);
/* Dump _ADR, _HID, _UID, _CID */
if (info->valid & ACPI_VALID_ADR) {
acpi_os_printf("_ADR: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(info->address));
} else {
acpi_os_printf("_ADR: <Not Present>\n");
}
if (info->valid & ACPI_VALID_HID) {
acpi_os_printf("_HID: %s\n", info->hardware_id.string);
} else {
acpi_os_printf("_HID: <Not Present>\n");
}
if (info->valid & ACPI_VALID_UID) {
acpi_os_printf("_UID: %s\n", info->unique_id.string);
} else {
acpi_os_printf("_UID: <Not Present>\n");
}
if (info->valid & ACPI_VALID_CID) {
for (i = 0; i < info->compatible_id_list.count; i++) {
acpi_os_printf("_CID: %s\n",
info->compatible_id_list.ids[i].string);
}
} else {
acpi_os_printf("_CID: <Not Present>\n");
}
ACPI_FREE(info);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_get_bus_info
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Display info about system busses.
*
******************************************************************************/
void acpi_db_get_bus_info(void)
{
/* Search all nodes in namespace */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL,
NULL);
}

View File

@@ -1,533 +0,0 @@
/*******************************************************************************
*
* Module Name: dbobject - ACPI object decode and display
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbobject")
/* Local prototypes */
static void acpi_db_decode_node(struct acpi_namespace_node *node);
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_method_info
*
* PARAMETERS: status - Method execution status
* walk_state - Current state of the parse tree walk
*
* RETURN: None
*
* DESCRIPTION: Called when a method has been aborted because of an error.
* Dumps the method execution stack, and the method locals/args,
* and disassembles the AML opcode that failed.
*
******************************************************************************/
void
acpi_db_dump_method_info(acpi_status status, struct acpi_walk_state *walk_state)
{
struct acpi_thread_state *thread;
/* Ignore control codes, they are not errors */
if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
return;
}
/* We may be executing a deferred opcode */
if (walk_state->deferred_node) {
acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
return;
}
/*
* If there is no Thread, we are not actually executing a method.
* This can happen when the iASL compiler calls the interpreter
* to perform constant folding.
*/
thread = walk_state->thread;
if (!thread) {
return;
}
/* Display the method locals and arguments */
acpi_os_printf("\n");
acpi_db_decode_locals(walk_state);
acpi_os_printf("\n");
acpi_db_decode_arguments(walk_state);
acpi_os_printf("\n");
}
/*******************************************************************************
*
* FUNCTION: acpi_db_decode_internal_object
*
* PARAMETERS: obj_desc - Object to be displayed
*
* RETURN: None
*
* DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
*
******************************************************************************/
void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc)
{
u32 i;
if (!obj_desc) {
acpi_os_printf(" Uninitialized");
return;
}
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf(" %p [%s]", obj_desc,
acpi_ut_get_descriptor_name(obj_desc));
return;
}
acpi_os_printf(" %s", acpi_ut_get_object_type_name(obj_desc));
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
acpi_os_printf(" %8.8X%8.8X",
ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
case ACPI_TYPE_STRING:
acpi_os_printf("(%u) \"%.24s",
obj_desc->string.length,
obj_desc->string.pointer);
if (obj_desc->string.length > 24) {
acpi_os_printf("...");
} else {
acpi_os_printf("\"");
}
break;
case ACPI_TYPE_BUFFER:
acpi_os_printf("(%u)", obj_desc->buffer.length);
for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
acpi_os_printf(" %2.2X", obj_desc->buffer.pointer[i]);
}
break;
default:
acpi_os_printf(" %p", obj_desc);
break;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_decode_node
*
* PARAMETERS: node - Object to be displayed
*
* RETURN: None
*
* DESCRIPTION: Short display of a namespace node
*
******************************************************************************/
static void acpi_db_decode_node(struct acpi_namespace_node *node)
{
acpi_os_printf("<Node> Name %4.4s",
acpi_ut_get_node_name(node));
if (node->flags & ANOBJ_METHOD_ARG) {
acpi_os_printf(" [Method Arg]");
}
if (node->flags & ANOBJ_METHOD_LOCAL) {
acpi_os_printf(" [Method Local]");
}
switch (node->type) {
/* These types have no attached object */
case ACPI_TYPE_DEVICE:
acpi_os_printf(" Device");
break;
case ACPI_TYPE_THERMAL:
acpi_os_printf(" Thermal Zone");
break;
default:
acpi_db_decode_internal_object(acpi_ns_get_attached_object
(node));
break;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_display_internal_object
*
* PARAMETERS: obj_desc - Object to be displayed
* walk_state - Current walk state
*
* RETURN: None
*
* DESCRIPTION: Short display of an internal object
*
******************************************************************************/
void
acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
u8 type;
acpi_os_printf("%p ", obj_desc);
if (!obj_desc) {
acpi_os_printf("<Null Object>\n");
return;
}
/* Decode the object type */
switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_PARSER:
acpi_os_printf("<Parser> ");
break;
case ACPI_DESC_TYPE_NAMED:
acpi_db_decode_node((struct acpi_namespace_node *)obj_desc);
break;
case ACPI_DESC_TYPE_OPERAND:
type = obj_desc->common.type;
if (type > ACPI_TYPE_LOCAL_MAX) {
acpi_os_printf(" Type %X [Invalid Type]", (u32)type);
return;
}
/* Decode the ACPI object type */
switch (obj_desc->common.type) {
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[%s] ",
acpi_ut_get_reference_name(obj_desc));
/* Decode the refererence */
switch (obj_desc->reference.class) {
case ACPI_REFCLASS_LOCAL:
acpi_os_printf("%X ",
obj_desc->reference.value);
if (walk_state) {
obj_desc = walk_state->local_variables
[obj_desc->reference.value].object;
acpi_os_printf("%p", obj_desc);
acpi_db_decode_internal_object
(obj_desc);
}
break;
case ACPI_REFCLASS_ARG:
acpi_os_printf("%X ",
obj_desc->reference.value);
if (walk_state) {
obj_desc = walk_state->arguments
[obj_desc->reference.value].object;
acpi_os_printf("%p", obj_desc);
acpi_db_decode_internal_object
(obj_desc);
}
break;
case ACPI_REFCLASS_INDEX:
switch (obj_desc->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
acpi_os_printf("%p",
obj_desc->reference.
object);
acpi_db_decode_internal_object
(obj_desc->reference.object);
break;
case ACPI_TYPE_PACKAGE:
acpi_os_printf("%p",
obj_desc->reference.
where);
if (!obj_desc->reference.where) {
acpi_os_printf
(" Uninitialized WHERE pointer");
} else {
acpi_db_decode_internal_object(*
(obj_desc->
reference.
where));
}
break;
default:
acpi_os_printf
("Unknown index target type");
break;
}
break;
case ACPI_REFCLASS_REFOF:
if (!obj_desc->reference.object) {
acpi_os_printf
("Uninitialized reference subobject pointer");
break;
}
/* Reference can be to a Node or an Operand object */
switch (ACPI_GET_DESCRIPTOR_TYPE
(obj_desc->reference.object)) {
case ACPI_DESC_TYPE_NAMED:
acpi_db_decode_node(obj_desc->reference.
object);
break;
case ACPI_DESC_TYPE_OPERAND:
acpi_db_decode_internal_object
(obj_desc->reference.object);
break;
default:
break;
}
break;
case ACPI_REFCLASS_NAME:
acpi_db_decode_node(obj_desc->reference.node);
break;
case ACPI_REFCLASS_DEBUG:
case ACPI_REFCLASS_TABLE:
acpi_os_printf("\n");
break;
default: /* Unknown reference class */
acpi_os_printf("%2.2X\n",
obj_desc->reference.class);
break;
}
break;
default:
acpi_os_printf("<Obj> ");
acpi_db_decode_internal_object(obj_desc);
break;
}
break;
default:
acpi_os_printf("<Not a valid ACPI Object Descriptor> [%s]",
acpi_ut_get_descriptor_name(obj_desc));
break;
}
acpi_os_printf("\n");
}
/*******************************************************************************
*
* FUNCTION: acpi_db_decode_locals
*
* PARAMETERS: walk_state - State for current method
*
* RETURN: None
*
* DESCRIPTION: Display all locals for the currently running control method
*
******************************************************************************/
void acpi_db_decode_locals(struct acpi_walk_state *walk_state)
{
u32 i;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
u8 display_locals = FALSE;
obj_desc = walk_state->method_desc;
node = walk_state->method_node;
if (!node) {
acpi_os_printf
("No method node (Executing subtree for buffer or opregion)\n");
return;
}
if (node->type != ACPI_TYPE_METHOD) {
acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
return;
}
/* Are any locals actually set? */
for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
obj_desc = walk_state->local_variables[i].object;
if (obj_desc) {
display_locals = TRUE;
break;
}
}
/* If any are set, only display the ones that are set */
if (display_locals) {
acpi_os_printf
("\nInitialized Local Variables for method [%4.4s]:\n",
acpi_ut_get_node_name(node));
for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
obj_desc = walk_state->local_variables[i].object;
if (obj_desc) {
acpi_os_printf(" Local%X: ", i);
acpi_db_display_internal_object(obj_desc,
walk_state);
}
}
} else {
acpi_os_printf
("No Local Variables are initialized for method [%4.4s]\n",
acpi_ut_get_node_name(node));
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_decode_arguments
*
* PARAMETERS: walk_state - State for current method
*
* RETURN: None
*
* DESCRIPTION: Display all arguments for the currently running control method
*
******************************************************************************/
void acpi_db_decode_arguments(struct acpi_walk_state *walk_state)
{
u32 i;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
u8 display_args = FALSE;
node = walk_state->method_node;
obj_desc = walk_state->method_desc;
if (!node) {
acpi_os_printf
("No method node (Executing subtree for buffer or opregion)\n");
return;
}
if (node->type != ACPI_TYPE_METHOD) {
acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
return;
}
/* Are any arguments actually set? */
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
obj_desc = walk_state->arguments[i].object;
if (obj_desc) {
display_args = TRUE;
break;
}
}
/* If any are set, only display the ones that are set */
if (display_args) {
acpi_os_printf("Initialized Arguments for Method [%4.4s]: "
"(%X arguments defined for method invocation)\n",
acpi_ut_get_node_name(node),
obj_desc->method.param_count);
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
obj_desc = walk_state->arguments[i].object;
if (obj_desc) {
acpi_os_printf(" Arg%u: ", i);
acpi_db_display_internal_object(obj_desc,
walk_state);
}
}
} else {
acpi_os_printf
("No Arguments are initialized for method [%4.4s]\n",
acpi_ut_get_node_name(node));
}
}

View File

@@ -1,546 +0,0 @@
/*******************************************************************************
*
* Module Name: dbstats - Generation and display of ACPI table statistics
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdebug.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbstats")
/* Local prototypes */
static void acpi_db_count_namespace_objects(void);
static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc);
static acpi_status
acpi_db_classify_one_object(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value);
#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
static void acpi_db_list_info(struct acpi_memory_list *list);
#endif
/*
* Statistics subcommands
*/
static struct acpi_db_argument_info acpi_db_stat_types[] = {
{"ALLOCATIONS"},
{"OBJECTS"},
{"MEMORY"},
{"MISC"},
{"TABLES"},
{"SIZES"},
{"STACK"},
{NULL} /* Must be null terminated */
};
#define CMD_STAT_ALLOCATIONS 0
#define CMD_STAT_OBJECTS 1
#define CMD_STAT_MEMORY 2
#define CMD_STAT_MISC 3
#define CMD_STAT_TABLES 4
#define CMD_STAT_SIZES 5
#define CMD_STAT_STACK 6
#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
/*******************************************************************************
*
* FUNCTION: acpi_db_list_info
*
* PARAMETERS: list - Memory list/cache to be displayed
*
* RETURN: None
*
* DESCRIPTION: Display information about the input memory list or cache.
*
******************************************************************************/
static void acpi_db_list_info(struct acpi_memory_list *list)
{
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
u32 outstanding;
#endif
acpi_os_printf("\n%s\n", list->list_name);
/* max_depth > 0 indicates a cache object */
if (list->max_depth > 0) {
acpi_os_printf
(" Cache: [Depth MaxD Avail Size] "
"%8.2X %8.2X %8.2X %8.2X\n", list->current_depth,
list->max_depth, list->max_depth - list->current_depth,
(list->current_depth * list->object_size));
}
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
if (list->max_depth > 0) {
acpi_os_printf
(" Cache: [Requests Hits Misses ObjSize] "
"%8.2X %8.2X %8.2X %8.2X\n", list->requests, list->hits,
list->requests - list->hits, list->object_size);
}
outstanding = acpi_db_get_cache_info(list);
if (list->object_size) {
acpi_os_printf
(" Mem: [Alloc Free Max CurSize Outstanding] "
"%8.2X %8.2X %8.2X %8.2X %8.2X\n", list->total_allocated,
list->total_freed, list->max_occupied,
outstanding * list->object_size, outstanding);
} else {
acpi_os_printf
(" Mem: [Alloc Free Max CurSize Outstanding Total] "
"%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n",
list->total_allocated, list->total_freed,
list->max_occupied, list->current_total_size, outstanding,
list->total_size);
}
#endif
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_db_enumerate_object
*
* PARAMETERS: obj_desc - Object to be counted
*
* RETURN: None
*
* DESCRIPTION: Add this object to the global counts, by object type.
* Limited recursion handles subobjects and packages, and this
* is probably acceptable within the AML debugger only.
*
******************************************************************************/
static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc)
{
u32 i;
if (!obj_desc) {
return;
}
/* Enumerate this object first */
acpi_gbl_num_objects++;
if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
acpi_gbl_obj_type_count_misc++;
} else {
acpi_gbl_obj_type_count[obj_desc->common.type]++;
}
/* Count the sub-objects */
switch (obj_desc->common.type) {
case ACPI_TYPE_PACKAGE:
for (i = 0; i < obj_desc->package.count; i++) {
acpi_db_enumerate_object(obj_desc->package.elements[i]);
}
break;
case ACPI_TYPE_DEVICE:
acpi_db_enumerate_object(obj_desc->device.notify_list[0]);
acpi_db_enumerate_object(obj_desc->device.notify_list[1]);
acpi_db_enumerate_object(obj_desc->device.handler);
break;
case ACPI_TYPE_BUFFER_FIELD:
if (acpi_ns_get_secondary_object(obj_desc)) {
acpi_gbl_obj_type_count[ACPI_TYPE_BUFFER_FIELD]++;
}
break;
case ACPI_TYPE_REGION:
acpi_gbl_obj_type_count[ACPI_TYPE_LOCAL_REGION_FIELD]++;
acpi_db_enumerate_object(obj_desc->region.handler);
break;
case ACPI_TYPE_POWER:
acpi_db_enumerate_object(obj_desc->power_resource.
notify_list[0]);
acpi_db_enumerate_object(obj_desc->power_resource.
notify_list[1]);
break;
case ACPI_TYPE_PROCESSOR:
acpi_db_enumerate_object(obj_desc->processor.notify_list[0]);
acpi_db_enumerate_object(obj_desc->processor.notify_list[1]);
acpi_db_enumerate_object(obj_desc->processor.handler);
break;
case ACPI_TYPE_THERMAL:
acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[0]);
acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[1]);
acpi_db_enumerate_object(obj_desc->thermal_zone.handler);
break;
default:
break;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_classify_one_object
*
* PARAMETERS: Callback for walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
* the parent namespace node.
*
******************************************************************************/
static acpi_status
acpi_db_classify_one_object(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
struct acpi_namespace_node *node;
union acpi_operand_object *obj_desc;
u32 type;
acpi_gbl_num_nodes++;
node = (struct acpi_namespace_node *)obj_handle;
obj_desc = acpi_ns_get_attached_object(node);
acpi_db_enumerate_object(obj_desc);
type = node->type;
if (type > ACPI_TYPE_NS_NODE_MAX) {
acpi_gbl_node_type_count_misc++;
} else {
acpi_gbl_node_type_count[type]++;
}
return (AE_OK);
#ifdef ACPI_FUTURE_IMPLEMENTATION
/* TBD: These need to be counted during the initial parsing phase */
if (acpi_ps_is_named_op(op->opcode)) {
num_nodes++;
}
if (is_method) {
num_method_elements++;
}
num_grammar_elements++;
op = acpi_ps_get_depth_next(root, op);
size_of_parse_tree = (num_grammar_elements - num_method_elements) *
(u32)sizeof(union acpi_parse_object);
size_of_method_trees =
num_method_elements * (u32)sizeof(union acpi_parse_object);
size_of_node_entries =
num_nodes * (u32)sizeof(struct acpi_namespace_node);
size_of_acpi_objects =
num_nodes * (u32)sizeof(union acpi_operand_object);
#endif
}
/*******************************************************************************
*
* FUNCTION: acpi_db_count_namespace_objects
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Count and classify the entire namespace, including all
* namespace nodes and attached objects.
*
******************************************************************************/
static void acpi_db_count_namespace_objects(void)
{
u32 i;
acpi_gbl_num_nodes = 0;
acpi_gbl_num_objects = 0;
acpi_gbl_obj_type_count_misc = 0;
for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX - 1); i++) {
acpi_gbl_obj_type_count[i] = 0;
acpi_gbl_node_type_count[i] = 0;
}
(void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, FALSE,
acpi_db_classify_one_object, NULL, NULL,
NULL);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_display_statistics
*
* PARAMETERS: type_arg - Subcommand
*
* RETURN: Status
*
* DESCRIPTION: Display various statistics
*
******************************************************************************/
acpi_status acpi_db_display_statistics(char *type_arg)
{
u32 i;
u32 temp;
acpi_ut_strupr(type_arg);
temp = acpi_db_match_argument(type_arg, acpi_db_stat_types);
if (temp == ACPI_TYPE_NOT_FOUND) {
acpi_os_printf("Invalid or unsupported argument\n");
return (AE_OK);
}
switch (temp) {
case CMD_STAT_ALLOCATIONS:
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
acpi_ut_dump_allocation_info();
#endif
break;
case CMD_STAT_TABLES:
acpi_os_printf("ACPI Table Information (not implemented):\n\n");
break;
case CMD_STAT_OBJECTS:
acpi_db_count_namespace_objects();
acpi_os_printf
("\nObjects defined in the current namespace:\n\n");
acpi_os_printf("%16.16s %10.10s %10.10s\n",
"ACPI_TYPE", "NODES", "OBJECTS");
for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
acpi_os_printf("%16.16s % 10ld% 10ld\n",
acpi_ut_get_type_name(i),
acpi_gbl_node_type_count[i],
acpi_gbl_obj_type_count[i]);
}
acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
acpi_gbl_node_type_count_misc,
acpi_gbl_obj_type_count_misc);
acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:",
acpi_gbl_num_nodes, acpi_gbl_num_objects);
break;
case CMD_STAT_MEMORY:
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
acpi_os_printf
("\n----Object Statistics (all in hex)---------\n");
acpi_db_list_info(acpi_gbl_global_list);
acpi_db_list_info(acpi_gbl_ns_node_list);
#endif
#ifdef ACPI_USE_LOCAL_CACHE
acpi_os_printf
("\n----Cache Statistics (all in hex)---------\n");
acpi_db_list_info(acpi_gbl_operand_cache);
acpi_db_list_info(acpi_gbl_ps_node_cache);
acpi_db_list_info(acpi_gbl_ps_node_ext_cache);
acpi_db_list_info(acpi_gbl_state_cache);
#endif
break;
case CMD_STAT_MISC:
acpi_os_printf("\nMiscellaneous Statistics:\n\n");
acpi_os_printf("Calls to AcpiPsFind:.. ........% 7ld\n",
acpi_gbl_ps_find_count);
acpi_os_printf("Calls to AcpiNsLookup:..........% 7ld\n",
acpi_gbl_ns_lookup_count);
acpi_os_printf("\n");
acpi_os_printf("Mutex usage:\n\n");
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
acpi_os_printf("%-28s: % 7ld\n",
acpi_ut_get_mutex_name(i),
acpi_gbl_mutex_info[i].use_count);
}
break;
case CMD_STAT_SIZES:
acpi_os_printf("\nInternal object sizes:\n\n");
acpi_os_printf("Common %3d\n",
sizeof(struct acpi_object_common));
acpi_os_printf("Number %3d\n",
sizeof(struct acpi_object_integer));
acpi_os_printf("String %3d\n",
sizeof(struct acpi_object_string));
acpi_os_printf("Buffer %3d\n",
sizeof(struct acpi_object_buffer));
acpi_os_printf("Package %3d\n",
sizeof(struct acpi_object_package));
acpi_os_printf("BufferField %3d\n",
sizeof(struct acpi_object_buffer_field));
acpi_os_printf("Device %3d\n",
sizeof(struct acpi_object_device));
acpi_os_printf("Event %3d\n",
sizeof(struct acpi_object_event));
acpi_os_printf("Method %3d\n",
sizeof(struct acpi_object_method));
acpi_os_printf("Mutex %3d\n",
sizeof(struct acpi_object_mutex));
acpi_os_printf("Region %3d\n",
sizeof(struct acpi_object_region));
acpi_os_printf("PowerResource %3d\n",
sizeof(struct acpi_object_power_resource));
acpi_os_printf("Processor %3d\n",
sizeof(struct acpi_object_processor));
acpi_os_printf("ThermalZone %3d\n",
sizeof(struct acpi_object_thermal_zone));
acpi_os_printf("RegionField %3d\n",
sizeof(struct acpi_object_region_field));
acpi_os_printf("BankField %3d\n",
sizeof(struct acpi_object_bank_field));
acpi_os_printf("IndexField %3d\n",
sizeof(struct acpi_object_index_field));
acpi_os_printf("Reference %3d\n",
sizeof(struct acpi_object_reference));
acpi_os_printf("Notify %3d\n",
sizeof(struct acpi_object_notify_handler));
acpi_os_printf("AddressSpace %3d\n",
sizeof(struct acpi_object_addr_handler));
acpi_os_printf("Extra %3d\n",
sizeof(struct acpi_object_extra));
acpi_os_printf("Data %3d\n",
sizeof(struct acpi_object_data));
acpi_os_printf("\n");
acpi_os_printf("ParseObject %3d\n",
sizeof(struct acpi_parse_obj_common));
acpi_os_printf("ParseObjectNamed %3d\n",
sizeof(struct acpi_parse_obj_named));
acpi_os_printf("ParseObjectAsl %3d\n",
sizeof(struct acpi_parse_obj_asl));
acpi_os_printf("OperandObject %3d\n",
sizeof(union acpi_operand_object));
acpi_os_printf("NamespaceNode %3d\n",
sizeof(struct acpi_namespace_node));
acpi_os_printf("AcpiObject %3d\n",
sizeof(union acpi_object));
acpi_os_printf("\n");
acpi_os_printf("Generic State %3d\n",
sizeof(union acpi_generic_state));
acpi_os_printf("Common State %3d\n",
sizeof(struct acpi_common_state));
acpi_os_printf("Control State %3d\n",
sizeof(struct acpi_control_state));
acpi_os_printf("Update State %3d\n",
sizeof(struct acpi_update_state));
acpi_os_printf("Scope State %3d\n",
sizeof(struct acpi_scope_state));
acpi_os_printf("Parse Scope %3d\n",
sizeof(struct acpi_pscope_state));
acpi_os_printf("Package State %3d\n",
sizeof(struct acpi_pkg_state));
acpi_os_printf("Thread State %3d\n",
sizeof(struct acpi_thread_state));
acpi_os_printf("Result Values %3d\n",
sizeof(struct acpi_result_values));
acpi_os_printf("Notify Info %3d\n",
sizeof(struct acpi_notify_info));
break;
case CMD_STAT_STACK:
#if defined(ACPI_DEBUG_OUTPUT)
temp =
(u32)ACPI_PTR_DIFF(acpi_gbl_entry_stack_pointer,
acpi_gbl_lowest_stack_pointer);
acpi_os_printf("\nSubsystem Stack Usage:\n\n");
acpi_os_printf("Entry Stack Pointer %p\n",
acpi_gbl_entry_stack_pointer);
acpi_os_printf("Lowest Stack Pointer %p\n",
acpi_gbl_lowest_stack_pointer);
acpi_os_printf("Stack Use %X (%u)\n", temp,
temp);
acpi_os_printf("Deepest Procedure Nesting %u\n",
acpi_gbl_deepest_nesting);
#endif
break;
default:
break;
}
acpi_os_printf("\n");
return (AE_OK);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,457 +0,0 @@
/*******************************************************************************
*
* Module Name: dbutils - AML debugger utilities
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbutils")
/* Local prototypes */
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root);
void acpi_db_dump_buffer(u32 address);
#endif
static char *gbl_hex_to_ascii = "0123456789ABCDEF";
/*******************************************************************************
*
* FUNCTION: acpi_db_match_argument
*
* PARAMETERS: user_argument - User command line
* arguments - Array of commands to match against
*
* RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found
*
* DESCRIPTION: Search command array for a command match
*
******************************************************************************/
acpi_object_type
acpi_db_match_argument(char *user_argument,
struct acpi_db_argument_info *arguments)
{
u32 i;
if (!user_argument || user_argument[0] == 0) {
return (ACPI_TYPE_NOT_FOUND);
}
for (i = 0; arguments[i].name; i++) {
if (strstr(arguments[i].name, user_argument) ==
arguments[i].name) {
return (i);
}
}
/* Argument not recognized */
return (ACPI_TYPE_NOT_FOUND);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_set_output_destination
*
* PARAMETERS: output_flags - Current flags word
*
* RETURN: None
*
* DESCRIPTION: Set the current destination for debugger output. Also sets
* the debug output level accordingly.
*
******************************************************************************/
void acpi_db_set_output_destination(u32 output_flags)
{
acpi_gbl_db_output_flags = (u8)output_flags;
if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
acpi_gbl_db_output_to_file) {
acpi_dbg_level = acpi_gbl_db_debug_level;
} else {
acpi_dbg_level = acpi_gbl_db_console_debug_level;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_external_object
*
* PARAMETERS: obj_desc - External ACPI object to dump
* level - Nesting level.
*
* RETURN: None
*
* DESCRIPTION: Dump the contents of an ACPI external object
*
******************************************************************************/
void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)
{
u32 i;
if (!obj_desc) {
acpi_os_printf("[Null Object]\n");
return;
}
for (i = 0; i < level; i++) {
acpi_os_printf(" ");
}
switch (obj_desc->type) {
case ACPI_TYPE_ANY:
acpi_os_printf("[Null Object] (Type=0)\n");
break;
case ACPI_TYPE_INTEGER:
acpi_os_printf("[Integer] = %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
case ACPI_TYPE_STRING:
acpi_os_printf("[String] Length %.2X = ",
obj_desc->string.length);
acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
acpi_os_printf("\n");
break;
case ACPI_TYPE_BUFFER:
acpi_os_printf("[Buffer] Length %.2X = ",
obj_desc->buffer.length);
if (obj_desc->buffer.length) {
if (obj_desc->buffer.length > 16) {
acpi_os_printf("\n");
}
acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
(u8,
obj_desc->buffer.pointer),
obj_desc->buffer.length,
DB_BYTE_DISPLAY, _COMPONENT);
} else {
acpi_os_printf("\n");
}
break;
case ACPI_TYPE_PACKAGE:
acpi_os_printf("[Package] Contains %u Elements:\n",
obj_desc->package.count);
for (i = 0; i < obj_desc->package.count; i++) {
acpi_db_dump_external_object(&obj_desc->package.
elements[i], level + 1);
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[Object Reference] = ");
acpi_db_display_internal_object(obj_desc->reference.handle,
NULL);
break;
case ACPI_TYPE_PROCESSOR:
acpi_os_printf("[Processor]\n");
break;
case ACPI_TYPE_POWER:
acpi_os_printf("[Power Resource]\n");
break;
default:
acpi_os_printf("[Unknown Type] %X\n", obj_desc->type);
break;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_prep_namestring
*
* PARAMETERS: name - String to prepare
*
* RETURN: None
*
* DESCRIPTION: Translate all forward slashes and dots to backslashes.
*
******************************************************************************/
void acpi_db_prep_namestring(char *name)
{
if (!name) {
return;
}
acpi_ut_strupr(name);
/* Convert a leading forward slash to a backslash */
if (*name == '/') {
*name = '\\';
}
/* Ignore a leading backslash, this is the root prefix */
if (ACPI_IS_ROOT_PREFIX(*name)) {
name++;
}
/* Convert all slash path separators to dots */
while (*name) {
if ((*name == '/') || (*name == '\\')) {
*name = '.';
}
name++;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_db_local_ns_lookup
*
* PARAMETERS: name - Name to lookup
*
* RETURN: Pointer to a namespace node, null on failure
*
* DESCRIPTION: Lookup a name in the ACPI namespace
*
* Note: Currently begins search from the root. Could be enhanced to use
* the current prefix (scope) node as the search beginning point.
*
******************************************************************************/
struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name)
{
char *internal_path;
acpi_status status;
struct acpi_namespace_node *node = NULL;
acpi_db_prep_namestring(name);
/* Build an internal namestring */
status = acpi_ns_internalize_name(name, &internal_path);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Invalid namestring: %s\n", name);
return (NULL);
}
/*
* Lookup the name.
* (Uses root node as the search starting point)
*/
status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE,
ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
NULL, &node);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not locate name: %s, %s\n",
name, acpi_format_exception(status));
}
ACPI_FREE(internal_path);
return (node);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_uint32_to_hex_string
*
* PARAMETERS: value - The value to be converted to string
* buffer - Buffer for result (not less than 11 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
*
* NOTE: It is the caller's responsibility to ensure that the length of buffer
* is sufficient.
*
******************************************************************************/
void acpi_db_uint32_to_hex_string(u32 value, char *buffer)
{
int i;
if (value == 0) {
strcpy(buffer, "0");
return;
}
buffer[8] = '\0';
for (i = 7; i >= 0; i--) {
buffer[i] = gbl_hex_to_ascii[value & 0x0F];
value = value >> 4;
}
}
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
* FUNCTION: acpi_db_second_pass_parse
*
* PARAMETERS: root - Root of the parse tree
*
* RETURN: Status
*
* DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
* second pass to parse the control methods
*
******************************************************************************/
acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root)
{
union acpi_parse_object *op = root;
union acpi_parse_object *method;
union acpi_parse_object *search_op;
union acpi_parse_object *start_op;
acpi_status status = AE_OK;
u32 base_aml_offset;
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_ENTRY();
acpi_os_printf("Pass two parse ....\n");
while (op) {
if (op->common.aml_opcode == AML_METHOD_OP) {
method = op;
/* Create a new walk state for the parse */
walk_state =
acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
return (AE_NO_MEMORY);
}
/* Init the Walk State */
walk_state->parser_state.aml =
walk_state->parser_state.aml_start =
method->named.data;
walk_state->parser_state.aml_end =
walk_state->parser_state.pkg_end =
method->named.data + method->named.length;
walk_state->parser_state.start_scope = op;
walk_state->descending_callback =
acpi_ds_load1_begin_op;
walk_state->ascending_callback = acpi_ds_load1_end_op;
/* Perform the AML parse */
status = acpi_ps_parse_aml(walk_state);
base_aml_offset =
(method->common.value.arg)->common.aml_offset + 1;
start_op = (method->common.value.arg)->common.next;
search_op = start_op;
while (search_op) {
search_op->common.aml_offset += base_aml_offset;
search_op =
acpi_ps_get_depth_next(start_op, search_op);
}
}
if (op->common.aml_opcode == AML_REGION_OP) {
/* TBD: [Investigate] this isn't quite the right thing to do! */
/*
*
* Method = (ACPI_DEFERRED_OP *) Op;
* Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length);
*/
}
if (ACPI_FAILURE(status)) {
break;
}
op = acpi_ps_get_depth_next(root, op);
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_dump_buffer
*
* PARAMETERS: address - Pointer to the buffer
*
* RETURN: None
*
* DESCRIPTION: Print a portion of a buffer
*
******************************************************************************/
void acpi_db_dump_buffer(u32 address)
{
acpi_os_printf("\nLocation %X:\n", address);
acpi_dbg_level |= ACPI_LV_TABLES;
acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY,
ACPI_UINT32_MAX);
}
#endif

View File

@@ -1,513 +0,0 @@
/*******************************************************************************
*
* Module Name: dbxface - AML Debugger external interfaces
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "amlcode.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbxface")
/* Local prototypes */
static acpi_status
acpi_db_start_command(struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
#ifdef ACPI_OBSOLETE_FUNCTIONS
void acpi_db_method_end(struct acpi_walk_state *walk_state);
#endif
/*******************************************************************************
*
* FUNCTION: acpi_db_start_command
*
* PARAMETERS: walk_state - Current walk
* op - Current executing Op, from AML interpreter
*
* RETURN: Status
*
* DESCRIPTION: Enter debugger command loop
*
******************************************************************************/
static acpi_status
acpi_db_start_command(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
/* TBD: [Investigate] are there namespace locking issues here? */
/* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
/* Go into the command loop and await next user command */
acpi_gbl_method_executing = TRUE;
status = AE_CTRL_TRUE;
while (status == AE_CTRL_TRUE) {
if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
/* Handshake with the front-end that gets user command lines */
acpi_os_release_mutex(acpi_gbl_db_command_complete);
status =
acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
ACPI_WAIT_FOREVER);
if (ACPI_FAILURE(status)) {
return (status);
}
} else {
/* Single threaded, we must get a command line ourselves */
/* Force output to console until a command is entered */
acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
/* Different prompt if method is executing */
if (!acpi_gbl_method_executing) {
acpi_os_printf("%1c ",
ACPI_DEBUGGER_COMMAND_PROMPT);
} else {
acpi_os_printf("%1c ",
ACPI_DEBUGGER_EXECUTE_PROMPT);
}
/* Get the user input line */
status = acpi_os_get_line(acpi_gbl_db_line_buf,
ACPI_DB_LINE_BUFFER_SIZE,
NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While parsing command line"));
return (status);
}
}
status =
acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
op);
}
/* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_single_step
*
* PARAMETERS: walk_state - Current walk
* op - Current executing op (from aml interpreter)
* opcode_class - Class of the current AML Opcode
*
* RETURN: Status
*
* DESCRIPTION: Called just before execution of an AML opcode.
*
******************************************************************************/
acpi_status
acpi_db_single_step(struct acpi_walk_state * walk_state,
union acpi_parse_object * op, u32 opcode_class)
{
union acpi_parse_object *next;
acpi_status status = AE_OK;
u32 original_debug_level;
union acpi_parse_object *display_op;
union acpi_parse_object *parent_op;
u32 aml_offset;
ACPI_FUNCTION_ENTRY();
#ifndef ACPI_APPLICATION
if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
return (AE_OK);
}
#endif
/* Check the abort flag */
if (acpi_gbl_abort_method) {
acpi_gbl_abort_method = FALSE;
return (AE_ABORT_METHOD);
}
aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
walk_state->parser_state.aml_start);
/* Check for single-step breakpoint */
if (walk_state->method_breakpoint &&
(walk_state->method_breakpoint <= aml_offset)) {
/* Check if the breakpoint has been reached or passed */
/* Hit the breakpoint, resume single step, reset breakpoint */
acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
acpi_gbl_cm_single_step = TRUE;
acpi_gbl_step_to_next_call = FALSE;
walk_state->method_breakpoint = 0;
}
/* Check for user breakpoint (Must be on exact Aml offset) */
else if (walk_state->user_breakpoint &&
(walk_state->user_breakpoint == aml_offset)) {
acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
aml_offset);
acpi_gbl_cm_single_step = TRUE;
acpi_gbl_step_to_next_call = FALSE;
walk_state->method_breakpoint = 0;
}
/*
* Check if this is an opcode that we are interested in --
* namely, opcodes that have arguments
*/
if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
return (AE_OK);
}
switch (opcode_class) {
case AML_CLASS_UNKNOWN:
case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */
return (AE_OK);
default:
/* All other opcodes -- continue */
break;
}
/*
* Under certain debug conditions, display this opcode and its operands
*/
if ((acpi_gbl_db_output_to_file) ||
(acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
if ((acpi_gbl_db_output_to_file) ||
(acpi_dbg_level & ACPI_LV_PARSE)) {
acpi_os_printf
("\n[AmlDebug] Next AML Opcode to execute:\n");
}
/*
* Display this op (and only this op - zero out the NEXT field
* temporarily, and disable parser trace output for the duration of
* the display because we don't want the extraneous debug output)
*/
original_debug_level = acpi_dbg_level;
acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
next = op->common.next;
op->common.next = NULL;
display_op = op;
parent_op = op->common.parent;
if (parent_op) {
if ((walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_PREDICATE_EXECUTING)) {
/*
* We are executing the predicate of an IF or WHILE statement
* Search upwards for the containing IF or WHILE so that the
* entire predicate can be displayed.
*/
while (parent_op) {
if ((parent_op->common.aml_opcode ==
AML_IF_OP)
|| (parent_op->common.aml_opcode ==
AML_WHILE_OP)) {
display_op = parent_op;
break;
}
parent_op = parent_op->common.parent;
}
} else {
while (parent_op) {
if ((parent_op->common.aml_opcode ==
AML_IF_OP)
|| (parent_op->common.aml_opcode ==
AML_ELSE_OP)
|| (parent_op->common.aml_opcode ==
AML_SCOPE_OP)
|| (parent_op->common.aml_opcode ==
AML_METHOD_OP)
|| (parent_op->common.aml_opcode ==
AML_WHILE_OP)) {
break;
}
display_op = parent_op;
parent_op = parent_op->common.parent;
}
}
}
/* Now we can display it */
#ifdef ACPI_DISASSEMBLER
acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
#endif
if ((op->common.aml_opcode == AML_IF_OP) ||
(op->common.aml_opcode == AML_WHILE_OP)) {
if (walk_state->control_state->common.value) {
acpi_os_printf
("Predicate = [True], IF block was executed\n");
} else {
acpi_os_printf
("Predicate = [False], Skipping IF block\n");
}
} else if (op->common.aml_opcode == AML_ELSE_OP) {
acpi_os_printf
("Predicate = [False], ELSE block was executed\n");
}
/* Restore everything */
op->common.next = next;
acpi_os_printf("\n");
if ((acpi_gbl_db_output_to_file) ||
(acpi_dbg_level & ACPI_LV_PARSE)) {
acpi_os_printf("\n");
}
acpi_dbg_level = original_debug_level;
}
/* If we are not single stepping, just continue executing the method */
if (!acpi_gbl_cm_single_step) {
return (AE_OK);
}
/*
* If we are executing a step-to-call command,
* Check if this is a method call.
*/
if (acpi_gbl_step_to_next_call) {
if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
/* Not a method call, just keep executing */
return (AE_OK);
}
/* Found a method call, stop executing */
acpi_gbl_step_to_next_call = FALSE;
}
/*
* If the next opcode is a method call, we will "step over" it
* by default.
*/
if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
/* Force no more single stepping while executing called method */
acpi_gbl_cm_single_step = FALSE;
/*
* Set the breakpoint on/before the call, it will stop execution
* as soon as we return
*/
walk_state->method_breakpoint = 1; /* Must be non-zero! */
}
status = acpi_db_start_command(walk_state, op);
/* User commands complete, continue execution of the interrupted method */
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_initialize_debugger
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Init and start debugger
*
******************************************************************************/
acpi_status acpi_initialize_debugger(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
/* Init globals */
acpi_gbl_db_buffer = NULL;
acpi_gbl_db_filename = NULL;
acpi_gbl_db_output_to_file = FALSE;
acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
acpi_gbl_db_opt_no_ini_methods = FALSE;
acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
if (!acpi_gbl_db_buffer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
/* Initial scope is the root */
acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
acpi_gbl_db_scope_buf[1] = 0;
acpi_gbl_db_scope_node = acpi_gbl_root_node;
/* Initialize user commands loop */
acpi_gbl_db_terminate_loop = FALSE;
/*
* If configured for multi-thread support, the debug executor runs in
* a separate thread so that the front end can be in another address
* space, environment, or even another machine.
*/
if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
/* These were created with one unit, grab it */
status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
ACPI_WAIT_FOREVER);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not get debugger mutex\n");
return_ACPI_STATUS(status);
}
status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
ACPI_WAIT_FOREVER);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not get debugger mutex\n");
return_ACPI_STATUS(status);
}
/* Create the debug execution thread to execute commands */
acpi_gbl_db_threads_terminated = FALSE;
status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
acpi_db_execute_thread, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not start debugger thread"));
acpi_gbl_db_threads_terminated = TRUE;
return_ACPI_STATUS(status);
}
} else {
acpi_gbl_db_thread_id = acpi_os_get_thread_id();
}
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
/*******************************************************************************
*
* FUNCTION: acpi_terminate_debugger
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Stop debugger
*
******************************************************************************/
void acpi_terminate_debugger(void)
{
/* Terminate the AML Debugger */
acpi_gbl_db_terminate_loop = TRUE;
if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
acpi_os_release_mutex(acpi_gbl_db_command_ready);
/* Wait the AML Debugger threads */
while (!acpi_gbl_db_threads_terminated) {
acpi_os_sleep(100);
}
}
if (acpi_gbl_db_buffer) {
acpi_os_free(acpi_gbl_db_buffer);
acpi_gbl_db_buffer = NULL;
}
/* Ensure that debug output is now disabled */
acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
}
ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
/*******************************************************************************
*
* FUNCTION: acpi_set_debugger_thread_id
*
* PARAMETERS: thread_id - Debugger thread ID
*
* RETURN: None
*
* DESCRIPTION: Set debugger thread ID
*
******************************************************************************/
void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
{
acpi_gbl_db_thread_id = thread_id;
}
ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)

View File

@@ -1,405 +0,0 @@
/******************************************************************************
*
* Module Name: dsargs - Support for execution of dynamic arguments for static
* objects (regions, fields, buffer fields, etc.)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsargs")
/* Local prototypes */
static acpi_status
acpi_ds_execute_arguments(struct acpi_namespace_node *node,
struct acpi_namespace_node *scope_node,
u32 aml_length, u8 *aml_start);
/*******************************************************************************
*
* FUNCTION: acpi_ds_execute_arguments
*
* PARAMETERS: node - Object NS node
* scope_node - Parent NS node
* aml_length - Length of executable AML
* aml_start - Pointer to the AML
*
* RETURN: Status.
*
* DESCRIPTION: Late (deferred) execution of region or field arguments
*
******************************************************************************/
static acpi_status
acpi_ds_execute_arguments(struct acpi_namespace_node *node,
struct acpi_namespace_node *scope_node,
u32 aml_length, u8 *aml_start)
{
acpi_status status;
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_TRACE(ds_execute_arguments);
/* Allocate a new parser op to be the root of the parsed tree */
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the Node for use in acpi_ps_parse_aml */
op->common.node = scope_node;
/* Create and initialize a new parser state */
walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
}
status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
goto cleanup;
}
/* Mark this parse as a deferred opcode */
walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
walk_state->deferred_node = node;
/* Pass1: Parse the entire declaration */
status = acpi_ps_parse_aml(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Get and init the Op created above */
op->common.node = node;
acpi_ps_delete_parse_tree(op);
/* Evaluate the deferred arguments */
op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
op->common.node = scope_node;
/* Create and initialize a new parser state */
walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Execute the opcode and arguments */
status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
aml_length, NULL, ACPI_IMODE_EXECUTE);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
goto cleanup;
}
/* Mark this execution as a deferred opcode */
walk_state->deferred_node = node;
status = acpi_ps_parse_aml(walk_state);
cleanup:
acpi_ps_delete_parse_tree(op);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_field_arguments
*
* PARAMETERS: obj_desc - A valid buffer_field object
*
* RETURN: Status.
*
* DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
* evaluation of these field attributes.
*
******************************************************************************/
acpi_status
acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
{
union acpi_operand_object *extra_desc;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
/* Get the AML pointer (method object) and buffer_field node */
extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->buffer_field.node;
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD,
node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
acpi_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_bank_field_arguments
*
* PARAMETERS: obj_desc - A valid bank_field object
*
* RETURN: Status.
*
* DESCRIPTION: Get bank_field bank_value. This implements the late
* evaluation of these field attributes.
*
******************************************************************************/
acpi_status
acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
{
union acpi_operand_object *extra_desc;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
/* Get the AML pointer (method object) and bank_field node */
extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->bank_field.node;
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
acpi_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ut_add_address_range(obj_desc->region.space_id,
obj_desc->region.address,
obj_desc->region.length, node);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_arguments
*
* PARAMETERS: obj_desc - A valid Buffer object
*
* RETURN: Status.
*
* DESCRIPTION: Get Buffer length and initializer byte list. This implements
* the late evaluation of these attributes.
*
******************************************************************************/
acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
{
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
/* Get the Buffer node */
node = obj_desc->buffer.node;
if (!node) {
ACPI_ERROR((AE_INFO,
"No pointer back to namespace node in buffer object %p",
obj_desc));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
status = acpi_ds_execute_arguments(node, node,
obj_desc->buffer.aml_length,
obj_desc->buffer.aml_start);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_package_arguments
*
* PARAMETERS: obj_desc - A valid Package object
*
* RETURN: Status.
*
* DESCRIPTION: Get Package length and initializer byte list. This implements
* the late evaluation of these attributes.
*
******************************************************************************/
acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
{
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
/* Get the Package node */
node = obj_desc->package.node;
if (!node) {
ACPI_ERROR((AE_INFO,
"No pointer back to namespace node in package %p",
obj_desc));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
status = acpi_ds_execute_arguments(node, node,
obj_desc->package.aml_length,
obj_desc->package.aml_start);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_region_arguments
*
* PARAMETERS: obj_desc - A valid region object
*
* RETURN: Status.
*
* DESCRIPTION: Get region address and length. This implements the late
* evaluation of these region attributes.
*
******************************************************************************/
acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
{
struct acpi_namespace_node *node;
acpi_status status;
union acpi_operand_object *extra_desc;
ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}
extra_desc = acpi_ns_get_secondary_object(obj_desc);
if (!extra_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the Region node */
node = obj_desc->region.node;
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_REGION, node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
acpi_ut_get_node_name(node),
extra_desc->extra.aml_start));
/* Execute the argument AML */
status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ut_add_address_range(obj_desc->region.space_id,
obj_desc->region.address,
obj_desc->region.length, node);
return_ACPI_STATUS(status);
}

View File

@@ -1,410 +0,0 @@
/******************************************************************************
*
* Module Name: dscontrol - Support for execution control opcodes -
* if/else/while/return
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dscontrol")
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_control_op
*
* PARAMETERS: walk_list - The list that owns the walk stack
* op - The control Op
*
* RETURN: Status
*
* DESCRIPTION: Handles all control ops encountered during control method
* execution.
*
******************************************************************************/
acpi_status
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status = AE_OK;
union acpi_generic_state *control_state;
ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n",
op, op->common.aml_opcode, walk_state));
switch (op->common.aml_opcode) {
case AML_WHILE_OP:
/*
* If this is an additional iteration of a while loop, continue.
* There is no need to allocate a new control state.
*/
if (walk_state->control_state) {
if (walk_state->control_state->control.
aml_predicate_start ==
(walk_state->parser_state.aml - 1)) {
/* Reset the state to start-of-loop */
walk_state->control_state->common.state =
ACPI_CONTROL_CONDITIONAL_EXECUTING;
break;
}
}
/*lint -fallthrough */
case AML_IF_OP:
/*
* IF/WHILE: Create a new control state to manage these
* constructs. We need to manage these as a stack, in order
* to handle nesting.
*/
control_state = acpi_ut_create_control_state();
if (!control_state) {
status = AE_NO_MEMORY;
break;
}
/*
* Save a pointer to the predicate for multiple executions
* of a loop
*/
control_state->control.aml_predicate_start =
walk_state->parser_state.aml - 1;
control_state->control.package_end =
walk_state->parser_state.pkg_end;
control_state->control.opcode = op->common.aml_opcode;
/* Push the control state on this walk's control stack */
acpi_ut_push_generic_state(&walk_state->control_state,
control_state);
break;
case AML_ELSE_OP:
/* Predicate is in the state object */
/* If predicate is true, the IF was executed, ignore ELSE part */
if (walk_state->last_predicate) {
status = AE_CTRL_TRUE;
}
break;
case AML_RETURN_OP:
break;
default:
break;
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_end_control_op
*
* PARAMETERS: walk_list - The list that owns the walk stack
* op - The control Op
*
* RETURN: Status
*
* DESCRIPTION: Handles all control ops encountered during control method
* execution.
*
******************************************************************************/
acpi_status
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
union acpi_parse_object * op)
{
acpi_status status = AE_OK;
union acpi_generic_state *control_state;
ACPI_FUNCTION_NAME(ds_exec_end_control_op);
switch (op->common.aml_opcode) {
case AML_IF_OP:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
/*
* Save the result of the predicate in case there is an
* ELSE to come
*/
walk_state->last_predicate =
(u8)walk_state->control_state->common.value;
/*
* Pop the control state that was created at the start
* of the IF and free it
*/
control_state =
acpi_ut_pop_generic_state(&walk_state->control_state);
acpi_ut_delete_generic_state(control_state);
break;
case AML_ELSE_OP:
break;
case AML_WHILE_OP:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
control_state = walk_state->control_state;
if (control_state->common.value) {
/* Predicate was true, the body of the loop was just executed */
/*
* This loop counter mechanism allows the interpreter to escape
* possibly infinite loops. This can occur in poorly written AML
* when the hardware does not respond within a while loop and the
* loop does not implement a timeout.
*/
control_state->control.loop_count++;
if (control_state->control.loop_count >
acpi_gbl_max_loop_iterations) {
status = AE_AML_INFINITE_LOOP;
break;
}
/*
* Go back and evaluate the predicate and maybe execute the loop
* another time
*/
status = AE_CTRL_PENDING;
walk_state->aml_last_while =
control_state->control.aml_predicate_start;
break;
}
/* Predicate was false, terminate this while loop */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[WHILE_OP] termination! Op=%p\n", op));
/* Pop this control state and free it */
control_state =
acpi_ut_pop_generic_state(&walk_state->control_state);
acpi_ut_delete_generic_state(control_state);
break;
case AML_RETURN_OP:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[RETURN_OP] Op=%p Arg=%p\n", op,
op->common.value.arg));
/*
* One optional operand -- the return value
* It can be either an immediate operand or a result that
* has been bubbled up the tree
*/
if (op->common.value.arg) {
/* Since we have a real Return(), delete any implicit return */
acpi_ds_clear_implicit_return(walk_state);
/* Return statement has an immediate operand */
status =
acpi_ds_create_operands(walk_state,
op->common.value.arg);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* If value being returned is a Reference (such as
* an arg or local), resolve it now because it may
* cease to exist at the end of the method.
*/
status =
acpi_ex_resolve_to_value(&walk_state->operands[0],
walk_state);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* Get the return value and save as the last result
* value. This is the only place where walk_state->return_desc
* is set to anything other than zero!
*/
walk_state->return_desc = walk_state->operands[0];
} else if (walk_state->result_count) {
/* Since we have a real Return(), delete any implicit return */
acpi_ds_clear_implicit_return(walk_state);
/*
* The return value has come from a previous calculation.
*
* If value being returned is a Reference (such as
* an arg or local), resolve it now because it may
* cease to exist at the end of the method.
*
* Allow references created by the Index operator to return
* unchanged.
*/
if ((ACPI_GET_DESCRIPTOR_TYPE
(walk_state->results->results.obj_desc[0]) ==
ACPI_DESC_TYPE_OPERAND)
&& ((walk_state->results->results.obj_desc[0])->
common.type == ACPI_TYPE_LOCAL_REFERENCE)
&& ((walk_state->results->results.obj_desc[0])->
reference.class != ACPI_REFCLASS_INDEX)) {
status =
acpi_ex_resolve_to_value(&walk_state->
results->results.
obj_desc[0],
walk_state);
if (ACPI_FAILURE(status)) {
return (status);
}
}
walk_state->return_desc =
walk_state->results->results.obj_desc[0];
} else {
/* No return operand */
if (walk_state->num_operands) {
acpi_ut_remove_reference(walk_state->
operands[0]);
}
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
walk_state->return_desc = NULL;
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Completed RETURN_OP State=%p, RetVal=%p\n",
walk_state, walk_state->return_desc));
/* End the control method execution right now */
status = AE_CTRL_TERMINATE;
break;
case AML_NOOP_OP:
/* Just do nothing! */
break;
case AML_BREAK_POINT_OP:
/*
* Set the single-step flag. This will cause the debugger (if present)
* to break to the console within the AML debugger at the start of the
* next AML instruction.
*/
ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
ACPI_DEBUGGER_EXEC(acpi_os_printf
("**break** Executed AML BreakPoint opcode\n"));
/* Call to the OSL in case OS wants a piece of the action */
status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
"Executed AML Breakpoint opcode");
break;
case AML_BREAK_OP:
case AML_CONTINUE_OP: /* ACPI 2.0 */
/* Pop and delete control states until we find a while */
while (walk_state->control_state &&
(walk_state->control_state->control.opcode !=
AML_WHILE_OP)) {
control_state =
acpi_ut_pop_generic_state(&walk_state->
control_state);
acpi_ut_delete_generic_state(control_state);
}
/* No while found? */
if (!walk_state->control_state) {
return (AE_AML_NO_WHILE);
}
/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
walk_state->aml_last_while =
walk_state->control_state->control.package_end;
/* Return status depending on opcode */
if (op->common.aml_opcode == AML_BREAK_OP) {
status = AE_CTRL_BREAK;
} else {
status = AE_CTRL_CONTINUE;
}
break;
default:
ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p",
op->common.aml_opcode, op));
status = AE_AML_BAD_OPCODE;
break;
}
return (status);
}

View File

@@ -1,231 +0,0 @@
/******************************************************************************
*
* Module Name: dsdebug - Parser/Interpreter interface - debugging
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acnamesp.h"
#ifdef ACPI_DISASSEMBLER
#include "acdisasm.h"
#endif
#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsdebug")
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
static void
acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
const char *message);
/*******************************************************************************
*
* FUNCTION: acpi_ds_print_node_pathname
*
* PARAMETERS: node - Object
* message - Prefix message
*
* DESCRIPTION: Print an object's full namespace pathname
* Manages allocation/freeing of a pathname buffer
*
******************************************************************************/
static void
acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
const char *message)
{
struct acpi_buffer buffer;
acpi_status status;
ACPI_FUNCTION_TRACE(ds_print_node_pathname);
if (!node) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]"));
return_VOID;
}
/* Convert handle to full pathname and print it (with supplied message) */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
if (ACPI_SUCCESS(status)) {
if (message) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ",
message));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)",
(char *)buffer.pointer, node));
ACPI_FREE(buffer.pointer);
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_dump_method_stack
*
* PARAMETERS: status - Method execution status
* walk_state - Current state of the parse tree walk
* op - Executing parse op
*
* RETURN: None
*
* DESCRIPTION: Called when a method has been aborted because of an error.
* Dumps the method execution stack.
*
******************************************************************************/
void
acpi_ds_dump_method_stack(acpi_status status,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
union acpi_parse_object *next;
struct acpi_thread_state *thread;
struct acpi_walk_state *next_walk_state;
struct acpi_namespace_node *previous_method = NULL;
union acpi_operand_object *method_desc;
ACPI_FUNCTION_TRACE(ds_dump_method_stack);
/* Ignore control codes, they are not errors */
if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
return_VOID;
}
/* We may be executing a deferred opcode */
if (walk_state->deferred_node) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Executing subtree for Buffer/Package/Region\n"));
return_VOID;
}
/*
* If there is no Thread, we are not actually executing a method.
* This can happen when the iASL compiler calls the interpreter
* to perform constant folding.
*/
thread = walk_state->thread;
if (!thread) {
return_VOID;
}
/* Display exception and method name */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"\n**** Exception %s during execution of method ",
acpi_format_exception(status)));
acpi_ds_print_node_pathname(walk_state->method_node, NULL);
/* Display stack of executing methods */
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
"\n\nMethod Execution Stack:\n"));
next_walk_state = thread->walk_state_list;
/* Walk list of linked walk states */
while (next_walk_state) {
method_desc = next_walk_state->method_desc;
if (method_desc) {
acpi_ex_stop_trace_method((struct acpi_namespace_node *)
method_desc->method.node,
method_desc, walk_state);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
" Method [%4.4s] executing: ",
acpi_ut_get_node_name(next_walk_state->
method_node)));
/* First method is the currently executing method */
if (next_walk_state == walk_state) {
if (op) {
/* Display currently executing ASL statement */
next = op->common.next;
op->common.next = NULL;
#ifdef ACPI_DISASSEMBLER
acpi_dm_disassemble(next_walk_state, op,
ACPI_UINT32_MAX);
#endif
op->common.next = next;
}
} else {
/*
* This method has called another method
* NOTE: the method call parse subtree is already deleted at this
* point, so we cannot disassemble the method invocation.
*/
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
"Call to method "));
acpi_ds_print_node_pathname(previous_method, NULL);
}
previous_method = next_walk_state->method_node;
next_walk_state = next_walk_state->next;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n"));
}
return_VOID;
}
#else
void
acpi_ds_dump_method_stack(acpi_status status,
struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
return;
}
#endif

View File

@@ -1,794 +0,0 @@
/******************************************************************************
*
* Module Name: dsfield - Dispatcher field routines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acparser.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsfield")
/* Local prototypes */
#ifdef ACPI_ASL_COMPILER
#include "acdisasm.h"
static acpi_status
acpi_ds_create_external_region(acpi_status lookup_status,
union acpi_parse_object *op,
char *path,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node);
#endif
static acpi_status
acpi_ds_get_field_names(struct acpi_create_field_info *info,
struct acpi_walk_state *walk_state,
union acpi_parse_object *arg);
#ifdef ACPI_ASL_COMPILER
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_external_region (iASL Disassembler only)
*
* PARAMETERS: lookup_status - Status from ns_lookup operation
* op - Op containing the Field definition and args
* path - Pathname of the region
* ` walk_state - Current method state
* node - Where the new region node is returned
*
* RETURN: Status
*
* DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new
* region node/object.
*
******************************************************************************/
static acpi_status
acpi_ds_create_external_region(acpi_status lookup_status,
union acpi_parse_object *op,
char *path,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node)
{
acpi_status status;
union acpi_operand_object *obj_desc;
if (lookup_status != AE_NOT_FOUND) {
return (lookup_status);
}
/*
* Table disassembly:
* operation_region not found. Generate an External for it, and
* insert the name into the namespace.
*/
acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
walk_state, node);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Must create and install a region object for the new node */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
return (AE_NO_MEMORY);
}
obj_desc->region.node = *node;
status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
return (status);
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_buffer_field
*
* PARAMETERS: op - Current parse op (create_XXField)
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Execute the create_field operators:
* create_bit_field_op,
* create_byte_field_op,
* create_word_field_op,
* create_dword_field_op,
* create_qword_field_op,
* create_field_op (all of which define a field in a buffer)
*
******************************************************************************/
acpi_status
acpi_ds_create_buffer_field(union acpi_parse_object *op,
struct acpi_walk_state *walk_state)
{
union acpi_parse_object *arg;
struct acpi_namespace_node *node;
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
u32 flags;
ACPI_FUNCTION_TRACE(ds_create_buffer_field);
/*
* Get the name_string argument (name of the new buffer_field)
*/
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* For create_field, name is the 4th argument */
arg = acpi_ps_get_arg(op, 3);
} else {
/* For all other create_XXXField operators, name is the 3rd argument */
arg = acpi_ps_get_arg(op, 2);
}
if (!arg) {
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
if (walk_state->deferred_node) {
node = walk_state->deferred_node;
status = AE_OK;
} else {
/* Execute flag should always be set when this function is entered */
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Creating new namespace node, should not already exist */
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/*
* Mark node temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
/* Enter the name_string into the namespace */
status =
acpi_ns_lookup(walk_state->scope_info,
arg->common.value.string, ACPI_TYPE_ANY,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
}
/*
* We could put the returned object (Node) on the object stack for later,
* but for now, we will put it in the "op" object that the parser uses,
* so we can get it again at the end of this scope.
*/
op->common.node = node;
/*
* If there is no object attached to the node, this node was just created
* and we need to create the field object. Otherwise, this was a lookup
* of an existing node and we don't want to create the field object again.
*/
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
return_ACPI_STATUS(AE_OK);
}
/*
* The Field definition is not fully parsed at this time.
* (We must save the address of the AML for the buffer and index operands)
*/
/* Create the buffer field object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* Remember location in AML stream of the field unit opcode and operands --
* since the buffer and index operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data;
second_desc->extra.aml_length = op->named.length;
obj_desc->buffer_field.node = node;
/* Attach constructed field descriptors to parent node */
status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
cleanup:
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_field_names
*
* PARAMETERS: info - create_field info structure
* ` walk_state - Current method state
* arg - First parser arg for the field name list
*
* RETURN: Status
*
* DESCRIPTION: Process all named fields in a field declaration. Names are
* entered into the namespace.
*
******************************************************************************/
static acpi_status
acpi_ds_get_field_names(struct acpi_create_field_info *info,
struct acpi_walk_state *walk_state,
union acpi_parse_object *arg)
{
acpi_status status;
u64 position;
union acpi_parse_object *child;
ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
/* First field starts at bit zero */
info->field_bit_position = 0;
/* Process all elements in the field list (of parse nodes) */
while (arg) {
/*
* Four types of field elements are handled:
* 1) name - Enters a new named field into the namespace
* 2) offset - specifies a bit offset
* 3) access_as - changes the access mode/attributes
* 4) connection - Associate a resource template with the field
*/
switch (arg->common.aml_opcode) {
case AML_INT_RESERVEDFIELD_OP:
position = (u64) info->field_bit_position
+ (u64) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
ACPI_ERROR((AE_INFO,
"Bit offset within field too large (> 0xFFFFFFFF)"));
return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position = (u32) position;
break;
case AML_INT_ACCESSFIELD_OP:
case AML_INT_EXTACCESSFIELD_OP:
/*
* Get new access_type, access_attribute, and access_length fields
* -- to be used for all field units that follow, until the
* end-of-field or another access_as keyword is encountered.
* NOTE. These three bytes are encoded in the integer value
* of the parseop for convenience.
*
* In field_flags, preserve the flag bits other than the
* ACCESS_TYPE bits.
*/
/* access_type (byte_acc, word_acc, etc.) */
info->field_flags = (u8)
((info->
field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
((u8)((u32)(arg->common.value.integer & 0x07))));
/* access_attribute (attrib_quick, attrib_byte, etc.) */
info->attribute =
(u8)((arg->common.value.integer >> 8) & 0xFF);
/* access_length (for serial/buffer protocols) */
info->access_length =
(u8)((arg->common.value.integer >> 16) & 0xFF);
break;
case AML_INT_CONNECTION_OP:
/*
* Clear any previous connection. New connection is used for all
* fields that follow, similar to access_as
*/
info->resource_buffer = NULL;
info->connection_node = NULL;
info->pin_number_index = 0;
/*
* A Connection() is either an actual resource descriptor (buffer)
* or a named reference to a resource template
*/
child = arg->common.value.arg;
if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
info->resource_buffer = child->named.data;
info->resource_length =
(u16)child->named.value.integer;
} else {
/* Lookup the Connection() namepath, it should already exist */
status = acpi_ns_lookup(walk_state->scope_info,
child->common.value.
name, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE,
ACPI_NS_DONT_OPEN_SCOPE,
walk_state,
&info->connection_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(child->common.
value.name,
status);
return_ACPI_STATUS(status);
}
}
break;
case AML_INT_NAMEDFIELD_OP:
/* Lookup the name, it should already exist */
status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name,
info->field_type,
ACPI_IMODE_EXECUTE,
ACPI_NS_DONT_OPEN_SCOPE,
walk_state, &info->field_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status);
return_ACPI_STATUS(status);
} else {
arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size;
/*
* If there is no object attached to the node, this node was
* just created and we need to create the field object.
* Otherwise, this was a lookup of an existing node and we
* don't want to create the field object again.
*/
if (!acpi_ns_get_attached_object
(info->field_node)) {
status = acpi_ex_prep_field_value(info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
/* Keep track of bit position for the next field */
position = (u64) info->field_bit_position
+ (u64) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
ACPI_ERROR((AE_INFO,
"Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
ACPI_CAST_PTR(char,
&info->field_node->
name)));
return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position += info->field_bit_length;
info->pin_number_index++; /* Index relative to previous Connection() */
break;
default:
ACPI_ERROR((AE_INFO,
"Invalid opcode in field list: 0x%X",
arg->common.aml_opcode));
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg = arg->common.next;
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_field
*
* PARAMETERS: op - Op containing the Field definition and args
* region_node - Object for the containing Operation Region
* ` walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Create a new field in the specified operation region
*
******************************************************************************/
acpi_status
acpi_ds_create_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_parse_object *arg;
struct acpi_create_field_info info;
ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
status =
acpi_ns_lookup(walk_state->scope_info,
arg->common.value.name, ACPI_TYPE_REGION,
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
walk_state, &region_node);
#ifdef ACPI_ASL_COMPILER
status = acpi_ds_create_external_region(status, arg,
arg->common.value.name,
walk_state,
&region_node);
#endif
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
return_ACPI_STATUS(status);
}
}
memset(&info, 0, sizeof(struct acpi_create_field_info));
/* Second arg is the field flags */
arg = arg->common.next;
info.field_flags = (u8) arg->common.value.integer;
info.attribute = 0;
/* Each remaining arg is a Named Field */
info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_field_objects
*
* PARAMETERS: op - Op containing the Field definition and args
* ` walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: For each "Field Unit" name in the argument list that is
* part of the field declaration, enter the name into the
* namespace.
*
******************************************************************************/
acpi_status
acpi_ds_init_field_objects(union acpi_parse_object *op,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_parse_object *arg = NULL;
struct acpi_namespace_node *node;
u8 type = 0;
u32 flags;
ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
/* Execute flag should always be set when this function is entered */
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
/* bank_field Op is deferred, just return OK */
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* Get the field_list argument for this opcode. This is the start of the
* list of field elements.
*/
switch (walk_state->opcode) {
case AML_FIELD_OP:
arg = acpi_ps_get_arg(op, 2);
type = ACPI_TYPE_LOCAL_REGION_FIELD;
break;
case AML_BANK_FIELD_OP:
arg = acpi_ps_get_arg(op, 4);
type = ACPI_TYPE_LOCAL_BANK_FIELD;
break;
case AML_INDEX_FIELD_OP:
arg = acpi_ps_get_arg(op, 3);
type = ACPI_TYPE_LOCAL_INDEX_FIELD;
break;
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Creating new namespace node(s), should not already exist */
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/*
* Mark node(s) temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
/*
* Walk the list of entries in the field_list
* Note: field_list can be of zero length. In this case, Arg will be NULL.
*/
while (arg) {
/*
* Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
* in the field names in order to enter them into the namespace.
*/
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name, type,
ACPI_IMODE_LOAD_PASS1, flags,
walk_state, &node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status);
if (status != AE_ALREADY_EXISTS) {
return_ACPI_STATUS(status);
}
/* Name already exists, just ignore this error */
status = AE_OK;
}
arg->common.node = node;
}
/* Get the next field element in the list */
arg = arg->common.next;
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_bank_field
*
* PARAMETERS: op - Op containing the Field definition and args
* region_node - Object for the containing Operation Region
* walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Create a new bank field in the specified operation region
*
******************************************************************************/
acpi_status
acpi_ds_create_bank_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_parse_object *arg;
struct acpi_create_field_info info;
ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
status =
acpi_ns_lookup(walk_state->scope_info,
arg->common.value.name, ACPI_TYPE_REGION,
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
walk_state, &region_node);
#ifdef ACPI_ASL_COMPILER
status = acpi_ds_create_external_region(status, arg,
arg->common.value.name,
walk_state,
&region_node);
#endif
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
return_ACPI_STATUS(status);
}
}
/* Second arg is the Bank Register (Field) (must already exist) */
arg = arg->common.next;
status =
acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.register_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
/*
* Third arg is the bank_value
* This arg is a term_arg, not a constant
* It will be evaluated later, by acpi_ds_eval_bank_field_operands
*/
arg = arg->common.next;
/* Fourth arg is the field flags */
arg = arg->common.next;
info.field_flags = (u8) arg->common.value.integer;
/* Each remaining arg is a Named Field */
info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
info.region_node = region_node;
/*
* Use Info.data_register_node to store bank_field Op
* It's safe because data_register_node will never be used when create bank field
* We store aml_start and aml_length in the bank_field Op for late evaluation
* Used in acpi_ex_prep_field_value(Info)
*
* TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
*/
info.data_register_node = (struct acpi_namespace_node *)op;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_index_field
*
* PARAMETERS: op - Op containing the Field definition and args
* region_node - Object for the containing Operation Region
* ` walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Create a new index field in the specified operation region
*
******************************************************************************/
acpi_status
acpi_ds_create_index_field(union acpi_parse_object *op,
struct acpi_namespace_node *region_node,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_parse_object *arg;
struct acpi_create_field_info info;
ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
/* First arg is the name of the Index register (must already exist) */
arg = op->common.value.arg;
status =
acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.register_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
/* Second arg is the data register (must already exist) */
arg = arg->common.next;
status =
acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT, walk_state,
&info.data_register_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
/* Next arg is the field flags */
arg = arg->common.next;
info.field_flags = (u8) arg->common.value.integer;
/* Each remaining arg is a Named Field */
info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status);
}

View File

@@ -1,263 +0,0 @@
/******************************************************************************
*
* Module Name: dsinit - Object initialization namespace walk
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acnamesp.h"
#include "actables.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsinit")
/* Local prototypes */
static acpi_status
acpi_ds_init_one_object(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_one_object
*
* PARAMETERS: obj_handle - Node for the object
* level - Current nesting level
* context - Points to a init info struct
* return_value - Not used
*
* RETURN: Status
*
* DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
* within the namespace.
*
* Currently, the only objects that require initialization are:
* 1) Methods
* 2) Operation Regions
*
******************************************************************************/
static acpi_status
acpi_ds_init_one_object(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
struct acpi_init_walk_info *info =
(struct acpi_init_walk_info *)context;
struct acpi_namespace_node *node =
(struct acpi_namespace_node *)obj_handle;
acpi_status status;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_ENTRY();
/*
* We are only interested in NS nodes owned by the table that
* was just loaded
*/
if (node->owner_id != info->owner_id) {
return (AE_OK);
}
info->object_count++;
/* And even then, we are only interested in a few object types */
switch (acpi_ns_get_type(obj_handle)) {
case ACPI_TYPE_REGION:
status = acpi_ds_initialize_region(obj_handle);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"During Region initialization %p [%4.4s]",
obj_handle,
acpi_ut_get_node_name(obj_handle)));
}
info->op_region_count++;
break;
case ACPI_TYPE_METHOD:
/*
* Auto-serialization support. We will examine each method that is
* not_serialized to determine if it creates any Named objects. If
* it does, it will be marked serialized to prevent problems if
* the method is entered by two or more threads and an attempt is
* made to create the same named object twice -- which results in
* an AE_ALREADY_EXISTS exception and method abort.
*/
info->method_count++;
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
break;
}
/* Ignore if already serialized */
if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
info->serial_method_count++;
break;
}
if (acpi_gbl_auto_serialize_methods) {
/* Parse/scan method and serialize it if necessary */
acpi_ds_auto_serialize_method(node, obj_desc);
if (obj_desc->method.
info_flags & ACPI_METHOD_SERIALIZED) {
/* Method was just converted to Serialized */
info->serial_method_count++;
info->serialized_method_count++;
break;
}
}
info->non_serial_method_count++;
break;
case ACPI_TYPE_DEVICE:
info->device_count++;
break;
default:
break;
}
/*
* We ignore errors from above, and always return OK, since
* we don't want to abort the walk on a single error.
*/
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_objects
*
* PARAMETERS: table_desc - Descriptor for parent ACPI table
* start_node - Root of subtree to be initialized.
*
* RETURN: Status
*
* DESCRIPTION: Walk the namespace starting at "StartNode" and perform any
* necessary initialization on the objects found therein
*
******************************************************************************/
acpi_status
acpi_ds_initialize_objects(u32 table_index,
struct acpi_namespace_node * start_node)
{
acpi_status status;
struct acpi_init_walk_info info;
struct acpi_table_header *table;
acpi_owner_id owner_id;
ACPI_FUNCTION_TRACE(ds_initialize_objects);
status = acpi_tb_get_owner_id(table_index, &owner_id);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
/* Set all init info to zero */
memset(&info, 0, sizeof(struct acpi_init_walk_info));
info.owner_id = owner_id;
info.table_index = table_index;
/* Walk entire namespace from the supplied root */
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* We don't use acpi_walk_namespace since we do not want to acquire
* the namespace reader lock.
*/
status =
acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
NULL, &info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
}
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* DSDT is always the first AML table */
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT)) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
"\nInitializing Namespace objects:\n"));
}
/* Summary of objects initialized */
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
"Table [%4.4s:%8.8s] (id %.2X) - %4u Objects with %3u Devices, "
"%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n",
table->signature, table->oem_table_id, owner_id,
info.object_count, info.device_count,
info.op_region_count, info.method_count,
info.serial_method_count,
info.non_serial_method_count,
info.serialized_method_count));
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n",
info.method_count, info.op_region_count));
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,840 +0,0 @@
/******************************************************************************
*
* Module Name: dsmethod - Parser/Interpreter interface - control method parsing
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmethod")
/* Local prototypes */
static acpi_status
acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
static acpi_status
acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
/*******************************************************************************
*
* FUNCTION: acpi_ds_auto_serialize_method
*
* PARAMETERS: node - Namespace Node of the method
* obj_desc - Method object attached to node
*
* RETURN: Status
*
* DESCRIPTION: Parse a control method AML to scan for control methods that
* need serialization due to the creation of named objects.
*
* NOTE: It is a bit of overkill to mark all such methods serialized, since
* there is only a problem if the method actually blocks during execution.
* A blocking operation is, for example, a Sleep() operation, or any access
* to an operation region. However, it is probably not possible to easily
* detect whether a method will block or not, so we simply mark all suspicious
* methods as serialized.
*
* NOTE2: This code is essentially a generic routine for parsing a single
* control method.
*
******************************************************************************/
acpi_status
acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
union acpi_operand_object *obj_desc)
{
acpi_status status;
union acpi_parse_object *op = NULL;
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node);
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"Method auto-serialization parse [%4.4s] %p\n",
acpi_ut_get_node_name(node), node));
/* Create/Init a root op for the method parse tree */
op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
acpi_ps_set_name(op, node->name.integer);
op->common.node = node;
/* Create and initialize a new walk state */
walk_state =
acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL);
if (!walk_state) {
acpi_ps_free_op(op);
return_ACPI_STATUS(AE_NO_MEMORY);
}
status =
acpi_ds_init_aml_walk(walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 0);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
acpi_ps_free_op(op);
return_ACPI_STATUS(status);
}
walk_state->descending_callback = acpi_ds_detect_named_opcodes;
/* Parse the method, scan for creation of named objects */
status = acpi_ps_parse_aml(walk_state);
acpi_ps_delete_parse_tree(op);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_detect_named_opcodes
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* out_op - Unused, required for parser interface
*
* RETURN: Status
*
* DESCRIPTION: Descending callback used during the loading of ACPI tables.
* Currently used to detect methods that must be marked serialized
* in order to avoid problems with the creation of named objects.
*
******************************************************************************/
static acpi_status
acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op)
{
ACPI_FUNCTION_NAME(acpi_ds_detect_named_opcodes);
/* We are only interested in opcodes that create a new name */
if (!
(walk_state->op_info->
flags & (AML_NAMED | AML_CREATE | AML_FIELD))) {
return (AE_OK);
}
/*
* At this point, we know we have a Named object opcode.
* Mark the method as serialized. Later code will create a mutex for
* this method to enforce serialization.
*
* Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
* Sync Level mechanism for this method, even though it is now serialized.
* Otherwise, there can be conflicts with existing ASL code that actually
* uses sync levels.
*/
walk_state->method_desc->method.sync_level = 0;
walk_state->method_desc->method.info_flags |=
(ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
walk_state->method_node->name.ascii,
walk_state->method_node, walk_state->op_info->name,
walk_state->opcode));
/* Abort the parse, no need to examine this method any further */
return (AE_CTRL_TERMINATE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_error
*
* PARAMETERS: status - Execution status
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Called on method error. Invoke the global exception handler if
* present, dump the method data if the debugger is configured
*
* Note: Allows the exception handler to change the status code
*
******************************************************************************/
acpi_status
acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
{
u32 aml_offset;
ACPI_FUNCTION_ENTRY();
/* Ignore AE_OK and control exception codes */
if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {
return (status);
}
/* Invoke the global exception handler */
if (acpi_gbl_exception_handler) {
/* Exit the interpreter, allow handler to execute methods */
acpi_ex_exit_interpreter();
/*
* Handler can map the exception code to anything it wants, including
* AE_OK, in which case the executing method will not be aborted.
*/
aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml,
walk_state->parser_state.
aml_start);
status = acpi_gbl_exception_handler(status,
walk_state->method_node ?
walk_state->method_node->
name.integer : 0,
walk_state->opcode,
aml_offset, NULL);
acpi_ex_enter_interpreter();
}
acpi_ds_clear_implicit_return(walk_state);
if (ACPI_FAILURE(status)) {
acpi_ds_dump_method_stack(status, walk_state, walk_state->op);
/* Display method locals/args if debugger is present */
#ifdef ACPI_DEBUGGER
acpi_db_dump_method_info(status, walk_state);
#endif
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_method_mutex
*
* PARAMETERS: obj_desc - The method object
*
* RETURN: Status
*
* DESCRIPTION: Create a mutex object for a serialized control method
*
******************************************************************************/
static acpi_status
acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)
{
union acpi_operand_object *mutex_desc;
acpi_status status;
ACPI_FUNCTION_TRACE(ds_create_method_mutex);
/* Create the new mutex object */
mutex_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
if (!mutex_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Create the actual OS Mutex */
status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_object_desc(mutex_desc);
return_ACPI_STATUS(status);
}
mutex_desc->mutex.sync_level = method_desc->method.sync_level;
method_desc->method.mutex = mutex_desc;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_begin_method_execution
*
* PARAMETERS: method_node - Node of the method
* obj_desc - The method object
* walk_state - current state, NULL if not yet executing
* a method.
*
* RETURN: Status
*
* DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
* increments the thread count, and waits at the method semaphore
* for clearance to execute.
*
******************************************************************************/
acpi_status
acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node);
if (!method_node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}
acpi_ex_start_trace_method(method_node, obj_desc, walk_state);
/* Prevent wraparound of thread count */
if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
ACPI_ERROR((AE_INFO,
"Method reached maximum reentrancy limit (255)"));
return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
/*
* If this method is serialized, we need to acquire the method mutex.
*/
if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
/*
* Create a mutex for the method if it is defined to be Serialized
* and a mutex has not already been created. We defer the mutex creation
* until a method is actually executed, to minimize the object count
*/
if (!obj_desc->method.mutex) {
status = acpi_ds_create_method_mutex(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/*
* The current_sync_level (per-thread) must be less than or equal to
* the sync level of the method. This mechanism provides some
* deadlock prevention.
*
* If the method was auto-serialized, we just ignore the sync level
* mechanism, because auto-serialization of methods can interfere
* with ASL code that actually uses sync levels.
*
* Top-level method invocation has no walk state at this point
*/
if (walk_state &&
(!(obj_desc->method.
info_flags & ACPI_METHOD_IGNORE_SYNC_LEVEL))
&& (walk_state->thread->current_sync_level >
obj_desc->method.mutex->mutex.sync_level)) {
ACPI_ERROR((AE_INFO,
"Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
acpi_ut_get_node_name(method_node),
walk_state->thread->current_sync_level));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/*
* Obtain the method mutex if necessary. Do not acquire mutex for a
* recursive call.
*/
if (!walk_state ||
!obj_desc->method.mutex->mutex.thread_id ||
(walk_state->thread->thread_id !=
obj_desc->method.mutex->mutex.thread_id)) {
/*
* Acquire the method mutex. This releases the interpreter if we
* block (and reacquires it before it returns)
*/
status =
acpi_ex_system_wait_mutex(obj_desc->method.mutex->
mutex.os_mutex,
ACPI_WAIT_FOREVER);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Update the mutex and walk info and save the original sync_level */
if (walk_state) {
obj_desc->method.mutex->mutex.
original_sync_level =
walk_state->thread->current_sync_level;
obj_desc->method.mutex->mutex.thread_id =
walk_state->thread->thread_id;
walk_state->thread->current_sync_level =
obj_desc->method.sync_level;
} else {
obj_desc->method.mutex->mutex.
original_sync_level =
obj_desc->method.mutex->mutex.sync_level;
obj_desc->method.mutex->mutex.thread_id =
acpi_os_get_thread_id();
}
}
/* Always increase acquisition depth */
obj_desc->method.mutex->mutex.acquisition_depth++;
}
/*
* Allocate an Owner ID for this method, only if this is the first thread
* to begin concurrent execution. We only need one owner_id, even if the
* method is invoked recursively.
*/
if (!obj_desc->method.owner_id) {
status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
/*
* Increment the method parse tree thread count since it has been
* reentered one more time (even if it is the same thread)
*/
obj_desc->method.thread_count++;
acpi_method_count++;
return_ACPI_STATUS(status);
cleanup:
/* On error, must release the method mutex (if present) */
if (obj_desc->method.mutex) {
acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_call_control_method
*
* PARAMETERS: thread - Info for this thread
* this_walk_state - Current walk state
* op - Current Op to be walked
*
* RETURN: Status
*
* DESCRIPTION: Transfer execution to a called control method
*
******************************************************************************/
acpi_status
acpi_ds_call_control_method(struct acpi_thread_state *thread,
struct acpi_walk_state *this_walk_state,
union acpi_parse_object *op)
{
acpi_status status;
struct acpi_namespace_node *method_node;
struct acpi_walk_state *next_walk_state = NULL;
union acpi_operand_object *obj_desc;
struct acpi_evaluate_info *info;
u32 i;
ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Calling method %p, currentstate=%p\n",
this_walk_state->prev_op, this_walk_state));
/*
* Get the namespace entry for the control method we are about to call
*/
method_node = this_walk_state->method_call_node;
if (!method_node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}
obj_desc = acpi_ns_get_attached_object(method_node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Init for new method, possibly wait on method mutex */
status = acpi_ds_begin_method_execution(method_node, obj_desc,
this_walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Begin method parse/execution. Create a new walk state */
next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
NULL, obj_desc, thread);
if (!next_walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* The resolved arguments were put on the previous walk state's operand
* stack. Operands on the previous walk state stack always
* start at index 0. Also, null terminate the list of arguments
*/
this_walk_state->operands[this_walk_state->num_operands] = NULL;
/*
* Allocate and initialize the evaluation information block
* TBD: this is somewhat inefficient, should change interface to
* ds_init_aml_walk. For now, keeps this struct off the CPU stack
*/
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
if (!info) {
status = AE_NO_MEMORY;
goto cleanup;
}
info->parameters = &this_walk_state->operands[0];
status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, info,
ACPI_IMODE_EXECUTE);
ACPI_FREE(info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Delete the operands on the previous walkstate operand stack
* (they were copied to new objects)
*/
for (i = 0; i < obj_desc->method.param_count; i++) {
acpi_ut_remove_reference(this_walk_state->operands[i]);
this_walk_state->operands[i] = NULL;
}
/* Clear the operand stack */
this_walk_state->num_operands = 0;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
method_node->name.ascii, next_walk_state));
/* Invoke an internal method if necessary */
if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
status =
obj_desc->method.dispatch.implementation(next_walk_state);
if (status == AE_OK) {
status = AE_CTRL_TERMINATE;
}
}
return_ACPI_STATUS(status);
cleanup:
/* On error, we must terminate the method properly */
acpi_ds_terminate_control_method(obj_desc, next_walk_state);
acpi_ds_delete_walk_state(next_walk_state);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_restart_control_method
*
* PARAMETERS: walk_state - State for preempted method (caller)
* return_desc - Return value from the called method
*
* RETURN: Status
*
* DESCRIPTION: Restart a method that was preempted by another (nested) method
* invocation. Handle the return value (if any) from the callee.
*
******************************************************************************/
acpi_status
acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
union acpi_operand_object *return_desc)
{
acpi_status status;
int same_as_implicit_return;
ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
acpi_ut_get_node_name(walk_state->method_node),
walk_state->method_call_op, return_desc));
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
" ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
walk_state->return_used,
walk_state->results, walk_state));
/* Did the called method return a value? */
if (return_desc) {
/* Is the implicit return object the same as the return desc? */
same_as_implicit_return =
(walk_state->implicit_return_obj == return_desc);
/* Are we actually going to use the return value? */
if (walk_state->return_used) {
/* Save the return value from the previous method */
status = acpi_ds_result_push(return_desc, walk_state);
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
return_ACPI_STATUS(status);
}
/*
* Save as THIS method's return value in case it is returned
* immediately to yet another method
*/
walk_state->return_desc = return_desc;
}
/*
* The following code is the optional support for the so-called
* "implicit return". Some AML code assumes that the last value of the
* method is "implicitly" returned to the caller, in the absence of an
* explicit return value.
*
* Just save the last result of the method as the return value.
*
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
else if (!acpi_ds_do_implicit_return
(return_desc, walk_state, FALSE)
|| same_as_implicit_return) {
/*
* Delete the return value if it will not be used by the
* calling method or remove one reference if the explicit return
* is the same as the implicit return value.
*/
acpi_ut_remove_reference(return_desc);
}
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_terminate_control_method
*
* PARAMETERS: method_desc - Method object
* walk_state - State associated with the method
*
* RETURN: None
*
* DESCRIPTION: Terminate a control method. Delete everything that the method
* created, delete all locals and arguments, and delete the parse
* tree if requested.
*
* MUTEX: Interpreter is locked
*
******************************************************************************/
void
acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
struct acpi_walk_state *walk_state)
{
ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
/* method_desc is required, walk_state is optional */
if (!method_desc) {
return_VOID;
}
if (walk_state) {
/* Delete all arguments and locals */
acpi_ds_method_data_delete_all(walk_state);
/*
* If method is serialized, release the mutex and restore the
* current sync level for this thread
*/
if (method_desc->method.mutex) {
/* Acquisition Depth handles recursive calls */
method_desc->method.mutex->mutex.acquisition_depth--;
if (!method_desc->method.mutex->mutex.acquisition_depth) {
walk_state->thread->current_sync_level =
method_desc->method.mutex->mutex.
original_sync_level;
acpi_os_release_mutex(method_desc->method.
mutex->mutex.os_mutex);
method_desc->method.mutex->mutex.thread_id = 0;
}
}
/*
* Delete any namespace objects created anywhere within the
* namespace by the execution of this method. Unless:
* 1) This method is a module-level executable code method, in which
* case we want make the objects permanent.
* 2) There are other threads executing the method, in which case we
* will wait until the last thread has completed.
*/
if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL)
&& (method_desc->method.thread_count == 1)) {
/* Delete any direct children of (created by) this method */
acpi_ns_delete_namespace_subtree(walk_state->
method_node);
/*
* Delete any objects that were created by this method
* elsewhere in the namespace (if any were created).
* Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
* deletion such that we don't have to perform an entire
* namespace walk for every control method execution.
*/
if (method_desc->method.
info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {
acpi_ns_delete_namespace_by_owner(method_desc->
method.
owner_id);
method_desc->method.info_flags &=
~ACPI_METHOD_MODIFIED_NAMESPACE;
}
}
}
/* Decrement the thread count on the method */
if (method_desc->method.thread_count) {
method_desc->method.thread_count--;
} else {
ACPI_ERROR((AE_INFO, "Invalid zero thread count in method"));
}
/* Are there any other threads currently executing this method? */
if (method_desc->method.thread_count) {
/*
* Additional threads. Do not release the owner_id in this case,
* we immediately reuse it for the next thread executing this method
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"*** Completed execution of one thread, %u threads remaining\n",
method_desc->method.thread_count));
} else {
/* This is the only executing thread for this method */
/*
* Support to dynamically change a method from not_serialized to
* Serialized if it appears that the method is incorrectly written and
* does not support multiple thread execution. The best example of this
* is if such a method creates namespace objects and blocks. A second
* thread will fail with an AE_ALREADY_EXISTS exception.
*
* This code is here because we must wait until the last thread exits
* before marking the method as serialized.
*/
if (method_desc->method.
info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
if (walk_state) {
ACPI_INFO((AE_INFO,
"Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
walk_state->method_node->name.
ascii));
}
/*
* Method tried to create an object twice and was marked as
* "pending serialized". The probable cause is that the method
* cannot handle reentrancy.
*
* The method was created as not_serialized, but it tried to create
* a named object and then blocked, causing the second thread
* entrance to begin and then fail. Workaround this problem by
* marking the method permanently as Serialized when the last
* thread exits here.
*/
method_desc->method.info_flags &=
~ACPI_METHOD_SERIALIZED_PENDING;
method_desc->method.info_flags |=
(ACPI_METHOD_SERIALIZED |
ACPI_METHOD_IGNORE_SYNC_LEVEL);
method_desc->method.sync_level = 0;
}
/* No more threads, we can free the owner_id */
if (!
(method_desc->method.
info_flags & ACPI_METHOD_MODULE_LEVEL)) {
acpi_ut_release_owner_id(&method_desc->method.owner_id);
}
}
acpi_ex_stop_trace_method((struct acpi_namespace_node *)method_desc->
method.node, method_desc, walk_state);
return_VOID;
}

View File

@@ -1,714 +0,0 @@
/*******************************************************************************
*
* Module Name: dsmthdat - control method arguments and local variables
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acnamesp.h"
#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmthdat")
/* Local prototypes */
static void
acpi_ds_method_data_delete_value(u8 type,
u32 index, struct acpi_walk_state *walk_state);
static acpi_status
acpi_ds_method_data_set_value(u8 type,
u32 index,
union acpi_operand_object *object,
struct acpi_walk_state *walk_state);
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_object_type
acpi_ds_method_data_get_type(u16 opcode,
u32 index, struct acpi_walk_state *walk_state);
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init
*
* PARAMETERS: walk_state - Current walk state object
*
* RETURN: Status
*
* DESCRIPTION: Initialize the data structures that hold the method's arguments
* and locals. The data struct is an array of namespace nodes for
* each - this allows ref_of and de_ref_of to work properly for these
* special data types.
*
* NOTES: walk_state fields are initialized to zero by the
* ACPI_ALLOCATE_ZEROED().
*
* A pseudo-Namespace Node is assigned to each argument and local
* so that ref_of() can return a pointer to the Node.
*
******************************************************************************/
void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
{
u32 i;
ACPI_FUNCTION_TRACE(ds_method_data_init);
/* Init the method arguments */
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
NAMEOF_ARG_NTE);
walk_state->arguments[i].name.integer |= (i << 24);
walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
walk_state->arguments[i].type = ACPI_TYPE_ANY;
walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
}
/* Init the method locals */
for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
NAMEOF_LOCAL_NTE);
walk_state->local_variables[i].name.integer |= (i << 24);
walk_state->local_variables[i].descriptor_type =
ACPI_DESC_TYPE_NAMED;
walk_state->local_variables[i].type = ACPI_TYPE_ANY;
walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_all
*
* PARAMETERS: walk_state - Current walk state object
*
* RETURN: None
*
* DESCRIPTION: Delete method locals and arguments. Arguments are only
* deleted if this method was called from another method.
*
******************************************************************************/
void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
{
u32 index;
ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
/* Detach the locals */
for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
if (walk_state->local_variables[index].object) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
index,
walk_state->local_variables[index].
object));
/* Detach object (if present) and remove a reference */
acpi_ns_detach_object(&walk_state->
local_variables[index]);
}
}
/* Detach the arguments */
for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
if (walk_state->arguments[index].object) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
index,
walk_state->arguments[index].object));
/* Detach object (if present) and remove a reference */
acpi_ns_detach_object(&walk_state->arguments[index]);
}
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init_args
*
* PARAMETERS: *params - Pointer to a parameter list for the method
* max_param_count - The arg count for this method
* walk_state - Current walk state object
*
* RETURN: Status
*
* DESCRIPTION: Initialize arguments for a method. The parameter list is a list
* of ACPI operand objects, either null terminated or whose length
* is defined by max_param_count.
*
******************************************************************************/
acpi_status
acpi_ds_method_data_init_args(union acpi_operand_object **params,
u32 max_param_count,
struct acpi_walk_state *walk_state)
{
acpi_status status;
u32 index = 0;
ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
if (!params) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"No param list passed to method\n"));
return_ACPI_STATUS(AE_OK);
}
/* Copy passed parameters into the new method stack frame */
while ((index < ACPI_METHOD_NUM_ARGS) &&
(index < max_param_count) && params[index]) {
/*
* A valid parameter.
* Store the argument in the method/walk descriptor.
* Do not copy the arg in order to implement call by reference
*/
status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
params[index],
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
index++;
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_node
*
* PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
* ACPI_REFCLASS_ARG
* index - Which Local or Arg whose type to get
* walk_state - Current walk state object
* node - Where the node is returned.
*
* RETURN: Status and node
*
* DESCRIPTION: Get the Node associated with a local or arg.
*
******************************************************************************/
acpi_status
acpi_ds_method_data_get_node(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node)
{
ACPI_FUNCTION_TRACE(ds_method_data_get_node);
/*
* Method Locals and Arguments are supported
*/
switch (type) {
case ACPI_REFCLASS_LOCAL:
if (index > ACPI_METHOD_MAX_LOCAL) {
ACPI_ERROR((AE_INFO,
"Local index %u is invalid (max %u)",
index, ACPI_METHOD_MAX_LOCAL));
return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
*node = &walk_state->local_variables[index];
break;
case ACPI_REFCLASS_ARG:
if (index > ACPI_METHOD_MAX_ARG) {
ACPI_ERROR((AE_INFO,
"Arg index %u is invalid (max %u)",
index, ACPI_METHOD_MAX_ARG));
return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
*node = &walk_state->arguments[index];
break;
default:
ACPI_ERROR((AE_INFO, "Type %u is invalid", type));
return_ACPI_STATUS(AE_TYPE);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_set_value
*
* PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
* ACPI_REFCLASS_ARG
* index - Which Local or Arg to get
* object - Object to be inserted into the stack entry
* walk_state - Current walk state object
*
* RETURN: Status
*
* DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
* Note: There is no "implicit conversion" for locals.
*
******************************************************************************/
static acpi_status
acpi_ds_method_data_set_value(u8 type,
u32 index,
union acpi_operand_object *object,
struct acpi_walk_state *walk_state)
{
acpi_status status;
struct acpi_namespace_node *node;
ACPI_FUNCTION_TRACE(ds_method_data_set_value);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"NewObj %p Type %2.2X, Refs=%u [%s]\n", object,
type, object->common.reference_count,
acpi_ut_get_type_name(object->common.type)));
/* Get the namespace node for the arg/local */
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Increment ref count so object can't be deleted while installed.
* NOTE: We do not copy the object in order to preserve the call by
* reference semantics of ACPI Control Method invocation.
* (See ACPI Specification 2.0C)
*/
acpi_ut_add_reference(object);
/* Install the object */
node->object = object;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_value
*
* PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
* ACPI_REFCLASS_ARG
* index - Which localVar or argument to get
* walk_state - Current walk state object
* dest_desc - Where Arg or Local value is returned
*
* RETURN: Status
*
* DESCRIPTION: Retrieve value of selected Arg or Local for this method
* Used only in acpi_ex_resolve_to_value().
*
******************************************************************************/
acpi_status
acpi_ds_method_data_get_value(u8 type,
u32 index,
struct acpi_walk_state *walk_state,
union acpi_operand_object **dest_desc)
{
acpi_status status;
struct acpi_namespace_node *node;
union acpi_operand_object *object;
ACPI_FUNCTION_TRACE(ds_method_data_get_value);
/* Validate the object descriptor */
if (!dest_desc) {
ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the object from the node */
object = node->object;
/* Examine the returned object, it must be valid. */
if (!object) {
/*
* Index points to uninitialized object.
* This means that either 1) The expected argument was
* not passed to the method, or 2) A local variable
* was referenced by the method (via the ASL)
* before it was initialized. Either case is an error.
*/
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
if (acpi_gbl_enable_interpreter_slack) {
object = acpi_ut_create_integer_object((u64) 0);
if (!object) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
node->object = object;
}
/* Otherwise, return the error */
else
switch (type) {
case ACPI_REFCLASS_ARG:
ACPI_ERROR((AE_INFO,
"Uninitialized Arg[%u] at node %p",
index, node));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
case ACPI_REFCLASS_LOCAL:
/*
* No error message for this case, will be trapped again later to
* detect and ignore cases of Store(local_x,local_x)
*/
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
default:
ACPI_ERROR((AE_INFO,
"Not a Arg/Local opcode: 0x%X",
type));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
/*
* The Index points to an initialized and valid object.
* Return an additional reference to the object
*/
*dest_desc = object;
acpi_ut_add_reference(object);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_value
*
* PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
* ACPI_REFCLASS_ARG
* index - Which localVar or argument to delete
* walk_state - Current walk state object
*
* RETURN: None
*
* DESCRIPTION: Delete the entry at Opcode:Index. Inserts
* a null into the stack slot after the object is deleted.
*
******************************************************************************/
static void
acpi_ds_method_data_delete_value(u8 type,
u32 index, struct acpi_walk_state *walk_state)
{
acpi_status status;
struct acpi_namespace_node *node;
union acpi_operand_object *object;
ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
/* Get the namespace node for the arg/local */
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Get the associated object */
object = acpi_ns_get_attached_object(node);
/*
* Undefine the Arg or Local by setting its descriptor
* pointer to NULL. Locals/Args can contain both
* ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
*/
node->object = NULL;
if ((object) &&
(ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
/*
* There is a valid object.
* Decrement the reference count by one to balance the
* increment when the object was stored.
*/
acpi_ut_remove_reference(object);
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_store_object_to_local
*
* PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
* ACPI_REFCLASS_ARG
* index - Which Local or Arg to set
* obj_desc - Value to be stored
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
* as the new value for the Arg or Local and the reference count
* for obj_desc is incremented.
*
******************************************************************************/
acpi_status
acpi_ds_store_object_to_local(u8 type,
u32 index,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
struct acpi_namespace_node *node;
union acpi_operand_object *current_obj_desc;
union acpi_operand_object *new_obj_desc;
ACPI_FUNCTION_TRACE(ds_store_object_to_local);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
type, index, obj_desc));
/* Parameter validation */
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
current_obj_desc = acpi_ns_get_attached_object(node);
if (current_obj_desc == obj_desc) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
obj_desc));
return_ACPI_STATUS(status);
}
/*
* If the reference count on the object is more than one, we must
* take a copy of the object before we store. A reference count
* of exactly 1 means that the object was just created during the
* evaluation of an expression, and we can safely use it since it
* is not used anywhere else.
*/
new_obj_desc = obj_desc;
if (obj_desc->common.reference_count > 1) {
status =
acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/*
* If there is an object already in this slot, we either
* have to delete it, or if this is an argument and there
* is an object reference stored there, we have to do
* an indirect store!
*/
if (current_obj_desc) {
/*
* Check for an indirect store if an argument
* contains an object reference (stored as an Node).
* We don't allow this automatic dereferencing for
* locals, since a store to a local should overwrite
* anything there, including an object reference.
*
* If both Arg0 and Local0 contain ref_of (Local4):
*
* Store (1, Arg0) - Causes indirect store to local4
* Store (1, Local0) - Stores 1 in local0, overwriting
* the reference to local4
* Store (1, de_refof (Local0)) - Causes indirect store to local4
*
* Weird, but true.
*/
if (type == ACPI_REFCLASS_ARG) {
/*
* If we have a valid reference object that came from ref_of(),
* do the indirect store
*/
if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
ACPI_DESC_TYPE_OPERAND)
&& (current_obj_desc->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
&& (current_obj_desc->reference.class ==
ACPI_REFCLASS_REFOF)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Arg (%p) is an ObjRef(Node), storing in node %p\n",
new_obj_desc,
current_obj_desc));
/*
* Store this object to the Node (perform the indirect store)
* NOTE: No implicit conversion is performed, as per the ACPI
* specification rules on storing to Locals/Args.
*/
status =
acpi_ex_store_object_to_node(new_obj_desc,
current_obj_desc->
reference.
object,
walk_state,
ACPI_NO_IMPLICIT_CONVERSION);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
acpi_ut_remove_reference(new_obj_desc);
}
return_ACPI_STATUS(status);
}
}
/* Delete the existing object before storing the new one */
acpi_ds_method_data_delete_value(type, index, walk_state);
}
/*
* Install the Obj descriptor (*new_obj_desc) into
* the descriptor for the Arg or Local.
* (increments the object reference count by one)
*/
status =
acpi_ds_method_data_set_value(type, index, new_obj_desc,
walk_state);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
acpi_ut_remove_reference(new_obj_desc);
}
return_ACPI_STATUS(status);
}
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_type
*
* PARAMETERS: opcode - Either AML_LOCAL_OP or AML_ARG_OP
* index - Which Local or Arg whose type to get
* walk_state - Current walk state object
*
* RETURN: Data type of current value of the selected Arg or Local
*
* DESCRIPTION: Get the type of the object stored in the Local or Arg
*
******************************************************************************/
acpi_object_type
acpi_ds_method_data_get_type(u16 opcode,
u32 index, struct acpi_walk_state *walk_state)
{
acpi_status status;
struct acpi_namespace_node *node;
union acpi_operand_object *object;
ACPI_FUNCTION_TRACE(ds_method_data_get_type);
/* Get the namespace node for the arg/local */
status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
if (ACPI_FAILURE(status)) {
return_VALUE((ACPI_TYPE_NOT_FOUND));
}
/* Get the object */
object = acpi_ns_get_attached_object(node);
if (!object) {
/* Uninitialized local/arg, return TYPE_ANY */
return_VALUE(ACPI_TYPE_ANY);
}
/* Get the object type */
return_VALUE(object->type);
}
#endif

View File

@@ -1,849 +0,0 @@
/******************************************************************************
*
* Module Name: dsobject - Dispatcher object management routines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acnamesp.h"
#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsobject")
/* Local prototypes */
static acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
union acpi_operand_object **obj_desc_ptr);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_object
*
* PARAMETERS: walk_state - Current walk state
* op - Parser object to be translated
* obj_desc_ptr - Where the ACPI internal object is returned
*
* RETURN: Status
*
* DESCRIPTION: Translate a parser Op object to the equivalent namespace object
* Simple objects are any objects other than a package object!
*
******************************************************************************/
static acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_operand_object *obj_desc;
acpi_status status;
acpi_object_type type;
ACPI_FUNCTION_TRACE(ds_build_internal_object);
*obj_desc_ptr = NULL;
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
/*
* This is a named object reference. If this name was
* previously looked up in the namespace, it was stored in this op.
* Otherwise, go ahead and look it up now
*/
if (!op->common.node) {
status = acpi_ns_lookup(walk_state->scope_info,
op->common.value.string,
ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT |
ACPI_NS_DONT_OPEN_SCOPE, NULL,
ACPI_CAST_INDIRECT_PTR(struct
acpi_namespace_node,
&(op->
common.
node)));
if (ACPI_FAILURE(status)) {
/* Check if we are resolving a named reference within a package */
if ((status == AE_NOT_FOUND)
&& (acpi_gbl_enable_interpreter_slack)
&&
((op->common.parent->common.aml_opcode ==
AML_PACKAGE_OP)
|| (op->common.parent->common.aml_opcode ==
AML_VAR_PACKAGE_OP))) {
/*
* We didn't find the target and we are populating elements
* of a package - ignore if slack enabled. Some ASL code
* contains dangling invalid references in packages and
* expects that no exception will be issued. Leave the
* element as a null element. It cannot be used, but it
* can be overwritten by subsequent ASL code - this is
* typically the case.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Ignoring unresolved reference in package [%4.4s]\n",
walk_state->
scope_info->scope.
node->name.ascii));
return_ACPI_STATUS(AE_OK);
} else {
ACPI_ERROR_NAMESPACE(op->common.value.
string, status);
}
return_ACPI_STATUS(status);
}
}
/* Special object resolution for elements of a package */
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode ==
AML_VAR_PACKAGE_OP)) {
/*
* Attempt to resolve the node to a value before we insert it into
* the package. If this is a reference to a common data type,
* resolve it immediately. According to the ACPI spec, package
* elements can only be "data objects" or method references.
* Attempt to resolve to an Integer, Buffer, String or Package.
* If cannot, return the named reference (for things like Devices,
* Methods, etc.) Buffer Fields and Fields will resolve to simple
* objects (int/buf/str/pkg).
*
* NOTE: References to things like Devices, Methods, Mutexes, etc.
* will remain as named references. This behavior is not described
* in the ACPI spec, but it appears to be an oversight.
*/
obj_desc =
ACPI_CAST_PTR(union acpi_operand_object,
op->common.node);
status =
acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
(struct
acpi_namespace_node,
&obj_desc),
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Special handling for Alias objects. We need to setup the type
* and the Op->Common.Node to point to the Alias target. Note,
* Alias has at most one level of indirection internally.
*/
type = op->common.node->type;
if (type == ACPI_TYPE_LOCAL_ALIAS) {
type = obj_desc->common.type;
op->common.node =
ACPI_CAST_PTR(struct acpi_namespace_node,
op->common.node->object);
}
switch (type) {
/*
* For these types, we need the actual node, not the subobject.
* However, the subobject did not get an extra reference count above.
*
* TBD: should ex_resolve_node_to_value be changed to fix this?
*/
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_THERMAL:
acpi_ut_add_reference(op->common.node->object);
/*lint -fallthrough */
/*
* For these types, we need the actual node, not the subobject.
* The subobject got an extra reference count in ex_resolve_node_to_value.
*/
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_METHOD:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_EVENT:
case ACPI_TYPE_REGION:
/* We will create a reference object for these types below */
break;
default:
/*
* All other types - the node was resolved to an actual
* object, we are done.
*/
goto exit;
}
}
}
/* Create and init a new internal ACPI object */
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
(op->common.aml_opcode))->
object_type);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
status =
acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
&obj_desc);
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
exit:
*obj_desc_ptr = obj_desc;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_buffer_obj
*
* PARAMETERS: walk_state - Current walk state
* op - Parser object to be translated
* buffer_length - Length of the buffer
* obj_desc_ptr - Where the ACPI internal object is returned
*
* RETURN: Status
*
* DESCRIPTION: Translate a parser Op package object to the equivalent
* namespace object
*
******************************************************************************/
acpi_status
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u32 buffer_length,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_parse_object *arg;
union acpi_operand_object *obj_desc;
union acpi_parse_object *byte_list;
u32 byte_list_length = 0;
ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
/*
* If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
* The buffer object already exists (from the NS node), otherwise it must
* be created.
*/
obj_desc = *obj_desc_ptr;
if (!obj_desc) {
/* Create a new buffer object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
}
/*
* Second arg is the buffer data (optional) byte_list can be either
* individual bytes or a string initializer. In either case, a
* byte_list appears in the AML.
*/
arg = op->common.value.arg; /* skip first arg */
byte_list = arg->named.next;
if (byte_list) {
if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
ACPI_ERROR((AE_INFO,
"Expecting bytelist, found AML opcode 0x%X in op %p",
byte_list->common.aml_opcode, byte_list));
acpi_ut_remove_reference(obj_desc);
return (AE_TYPE);
}
byte_list_length = (u32) byte_list->common.value.integer;
}
/*
* The buffer length (number of bytes) will be the larger of:
* 1) The specified buffer length and
* 2) The length of the initializer byte list
*/
obj_desc->buffer.length = buffer_length;
if (byte_list_length > buffer_length) {
obj_desc->buffer.length = byte_list_length;
}
/* Allocate the buffer */
if (obj_desc->buffer.length == 0) {
obj_desc->buffer.pointer = NULL;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Buffer defined with zero length in AML, creating\n"));
} else {
obj_desc->buffer.pointer =
ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
if (!obj_desc->buffer.pointer) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize buffer from the byte_list (if present) */
if (byte_list) {
memcpy(obj_desc->buffer.pointer, byte_list->named.data,
byte_list_length);
}
}
obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_package_obj
*
* PARAMETERS: walk_state - Current walk state
* op - Parser object to be translated
* element_count - Number of elements in the package - this is
* the num_elements argument to Package()
* obj_desc_ptr - Where the ACPI internal object is returned
*
* RETURN: Status
*
* DESCRIPTION: Translate a parser Op package object to the equivalent
* namespace object
*
* NOTE: The number of elements in the package will be always be the num_elements
* count, regardless of the number of elements in the package list. If
* num_elements is smaller, only that many package list elements are used.
* if num_elements is larger, the Package object is padded out with
* objects of type Uninitialized (as per ACPI spec.)
*
* Even though the ASL compilers do not allow num_elements to be smaller
* than the Package list length (for the fixed length package opcode), some
* BIOS code modifies the AML on the fly to adjust the num_elements, and
* this code compensates for that. This also provides compatibility with
* other AML interpreters.
*
******************************************************************************/
acpi_status
acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u32 element_count,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_parse_object *arg;
union acpi_parse_object *parent;
union acpi_operand_object *obj_desc = NULL;
acpi_status status = AE_OK;
u32 i;
u16 index;
u16 reference_count;
ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
/* Find the parent of a possibly nested package */
parent = op->common.parent;
while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
(parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
parent = parent->common.parent;
}
/*
* If we are evaluating a Named package object "Name (xxxx, Package)",
* the package object already exists, otherwise it must be created.
*/
obj_desc = *obj_desc_ptr;
if (!obj_desc) {
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
obj_desc->package.node = parent->common.node;
}
/*
* Allocate the element array (array of pointers to the individual
* objects) based on the num_elements parameter. Add an extra pointer slot
* so that the list is always null terminated.
*/
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
element_count +
1) * sizeof(void *));
if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
}
obj_desc->package.count = element_count;
/*
* Initialize the elements of the package, up to the num_elements count.
* Package is automatically padded with uninitialized (NULL) elements
* if num_elements is greater than the package list length. Likewise,
* Package is truncated if num_elements is less than the list length.
*/
arg = op->common.value.arg;
arg = arg->common.next;
for (i = 0; arg && (i < element_count); i++) {
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
if (arg->common.node->type == ACPI_TYPE_METHOD) {
/*
* A method reference "looks" to the parser to be a method
* invocation, so we special case it here
*/
arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
status =
acpi_ds_build_internal_object(walk_state,
arg,
&obj_desc->
package.
elements[i]);
} else {
/* This package element is already built, just get it */
obj_desc->package.elements[i] =
ACPI_CAST_PTR(union acpi_operand_object,
arg->common.node);
}
} else {
status = acpi_ds_build_internal_object(walk_state, arg,
&obj_desc->
package.
elements[i]);
}
if (*obj_desc_ptr) {
/* Existing package, get existing reference count */
reference_count =
(*obj_desc_ptr)->common.reference_count;
if (reference_count > 1) {
/* Make new element ref count match original ref count */
for (index = 0; index < (reference_count - 1);
index++) {
acpi_ut_add_reference((obj_desc->
package.
elements[i]));
}
}
}
arg = arg->common.next;
}
/* Check for match between num_elements and actual length of package_list */
if (arg) {
/*
* num_elements was exhausted, but there are remaining elements in the
* package_list. Truncate the package to num_elements.
*
* Note: technically, this is an error, from ACPI spec: "It is an error
* for NumElements to be less than the number of elements in the
* PackageList". However, we just print a message and
* no exception is returned. This provides Windows compatibility. Some
* BIOSs will alter the num_elements on the fly, creating this type
* of ill-formed package object.
*/
while (arg) {
/*
* We must delete any package elements that were created earlier
* and are not going to be used because of the package truncation.
*/
if (arg->common.node) {
acpi_ut_remove_reference(ACPI_CAST_PTR
(union
acpi_operand_object,
arg->common.node));
arg->common.node = NULL;
}
/* Find out how many elements there really are */
i++;
arg = arg->common.next;
}
ACPI_INFO((AE_INFO,
"Actual Package length (%u) is larger than NumElements field (%u), truncated",
i, element_count));
} else if (i < element_count) {
/*
* Arg list (elements) was exhausted, but we did not reach num_elements count.
* Note: this is not an error, the package is padded out with NULLs.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Package List length (%u) smaller than NumElements count (%u), padded with null elements\n",
i, element_count));
}
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_node
*
* PARAMETERS: walk_state - Current walk state
* node - NS Node to be initialized
* op - Parser object to be translated
*
* RETURN: Status
*
* DESCRIPTION: Create the object to be associated with a namespace node
*
******************************************************************************/
acpi_status
acpi_ds_create_node(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
/*
* Because of the execution pass through the non-control-method
* parts of the table, we can arrive here twice. Only init
* the named object node the first time through
*/
if (acpi_ns_get_attached_object(node)) {
return_ACPI_STATUS(AE_OK);
}
if (!op->common.value.arg) {
/* No arguments, there is nothing to do */
return_ACPI_STATUS(AE_OK);
}
/* Build an internal object for the argument(s) */
status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Re-type the object according to its argument */
node->type = obj_desc->common.type;
/* Attach obj to node */
status = acpi_ns_attach_object(node, obj_desc, node->type);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
#endif /* ACPI_NO_METHOD_EXECUTION */
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_object_from_op
*
* PARAMETERS: walk_state - Current walk state
* op - Parser op used to init the internal object
* opcode - AML opcode associated with the object
* ret_obj_desc - Namespace object to be initialized
*
* RETURN: Status
*
* DESCRIPTION: Initialize a namespace object from a parser Op and its
* associated arguments. The namespace object is a more compact
* representation of the Op and its arguments.
*
******************************************************************************/
acpi_status
acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
u16 opcode,
union acpi_operand_object **ret_obj_desc)
{
const struct acpi_opcode_info *op_info;
union acpi_operand_object *obj_desc;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ds_init_object_from_op);
obj_desc = *ret_obj_desc;
op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Unknown opcode */
return_ACPI_STATUS(AE_TYPE);
}
/* Perform per-object initialization */
switch (obj_desc->common.type) {
case ACPI_TYPE_BUFFER:
/*
* Defer evaluation of Buffer term_arg operand
*/
obj_desc->buffer.node =
ACPI_CAST_PTR(struct acpi_namespace_node,
walk_state->operands[0]);
obj_desc->buffer.aml_start = op->named.data;
obj_desc->buffer.aml_length = op->named.length;
break;
case ACPI_TYPE_PACKAGE:
/*
* Defer evaluation of Package term_arg operand
*/
obj_desc->package.node =
ACPI_CAST_PTR(struct acpi_namespace_node,
walk_state->operands[0]);
obj_desc->package.aml_start = op->named.data;
obj_desc->package.aml_length = op->named.length;
break;
case ACPI_TYPE_INTEGER:
switch (op_info->type) {
case AML_TYPE_CONSTANT:
/*
* Resolve AML Constants here - AND ONLY HERE!
* All constants are integers.
* We mark the integer with a flag that indicates that it started
* life as a constant -- so that stores to constants will perform
* as expected (noop). zero_op is used as a placeholder for optional
* target operands.
*/
obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
switch (opcode) {
case AML_ZERO_OP:
obj_desc->integer.value = 0;
break;
case AML_ONE_OP:
obj_desc->integer.value = 1;
break;
case AML_ONES_OP:
obj_desc->integer.value = ACPI_UINT64_MAX;
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
(void)acpi_ex_truncate_for32bit_table(obj_desc);
#endif
break;
case AML_REVISION_OP:
obj_desc->integer.value = ACPI_CA_VERSION;
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown constant opcode 0x%X",
opcode));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
case AML_TYPE_LITERAL:
obj_desc->integer.value = op->common.value.integer;
#ifndef ACPI_NO_METHOD_EXECUTION
if (acpi_ex_truncate_for32bit_table(obj_desc)) {
/* Warn if we found a 64-bit constant in a 32-bit table */
ACPI_WARNING((AE_INFO,
"Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
ACPI_FORMAT_UINT64(op->common.
value.integer),
(u32)obj_desc->integer.value));
}
#endif
break;
default:
ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X",
op_info->type));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
case ACPI_TYPE_STRING:
obj_desc->string.pointer = op->common.value.string;
obj_desc->string.length = (u32)strlen(op->common.value.string);
/*
* The string is contained in the ACPI table, don't ever try
* to delete it
*/
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
case ACPI_TYPE_METHOD:
break;
case ACPI_TYPE_LOCAL_REFERENCE:
switch (op_info->type) {
case AML_TYPE_LOCAL_VARIABLE:
/* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
obj_desc->reference.value =
((u32)opcode) - AML_LOCAL_OP;
obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
#ifndef ACPI_NO_METHOD_EXECUTION
status =
acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
obj_desc->reference.
value, walk_state,
ACPI_CAST_INDIRECT_PTR
(struct
acpi_namespace_node,
&obj_desc->reference.
object));
#endif
break;
case AML_TYPE_METHOD_ARGUMENT:
/* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
obj_desc->reference.value = ((u32)opcode) - AML_ARG_OP;
obj_desc->reference.class = ACPI_REFCLASS_ARG;
#ifndef ACPI_NO_METHOD_EXECUTION
status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
obj_desc->
reference.value,
walk_state,
ACPI_CAST_INDIRECT_PTR
(struct
acpi_namespace_node,
&obj_desc->
reference.
object));
#endif
break;
default: /* Object name or Debug object */
switch (op->common.aml_opcode) {
case AML_INT_NAMEPATH_OP:
/* Node was saved in Op */
obj_desc->reference.node = op->common.node;
obj_desc->reference.object =
op->common.node->object;
obj_desc->reference.class = ACPI_REFCLASS_NAME;
break;
case AML_DEBUG_OP:
obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
break;
default:
ACPI_ERROR((AE_INFO,
"Unimplemented reference type for AML opcode: 0x%4.4X",
opcode));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
}
break;
default:
ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X",
obj_desc->common.type));
status = AE_AML_OPERAND_TYPE;
break;
}
return_ACPI_STATUS(status);
}

View File

@@ -1,766 +0,0 @@
/******************************************************************************
*
* Module Name: dsopcode - Dispatcher support for regions and fields
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acevents.h"
#include "actables.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsopcode")
/* Local prototypes */
static acpi_status
acpi_ds_init_buffer_field(u16 aml_opcode,
union acpi_operand_object *obj_desc,
union acpi_operand_object *buffer_desc,
union acpi_operand_object *offset_desc,
union acpi_operand_object *length_desc,
union acpi_operand_object *result_desc);
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_region
*
* PARAMETERS: obj_handle - Region namespace node
*
* RETURN: Status
*
* DESCRIPTION: Front end to ev_initialize_region
*
******************************************************************************/
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
{
union acpi_operand_object *obj_desc;
acpi_status status;
obj_desc = acpi_ns_get_attached_object(obj_handle);
/* Namespace is NOT locked */
status = acpi_ev_initialize_region(obj_desc, FALSE);
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_buffer_field
*
* PARAMETERS: aml_opcode - create_xxx_field
* obj_desc - buffer_field object
* buffer_desc - Host Buffer
* offset_desc - Offset into buffer
* length_desc - Length of field (CREATE_FIELD_OP only)
* result_desc - Where to store the result
*
* RETURN: Status
*
* DESCRIPTION: Perform actual initialization of a buffer field
*
******************************************************************************/
static acpi_status
acpi_ds_init_buffer_field(u16 aml_opcode,
union acpi_operand_object *obj_desc,
union acpi_operand_object *buffer_desc,
union acpi_operand_object *offset_desc,
union acpi_operand_object *length_desc,
union acpi_operand_object *result_desc)
{
u32 offset;
u32 bit_offset;
u32 bit_count;
u8 field_flags;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
/* Host object must be a Buffer */
if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
"Target of Create Field is not a Buffer object - %s",
acpi_ut_get_object_type_name(buffer_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
/*
* The last parameter to all of these opcodes (result_desc) started
* out as a name_string, and should therefore now be a NS node
* after resolution in acpi_ex_resolve_operands().
*/
if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
ACPI_ERROR((AE_INFO,
"(%s) destination not a NS Node [%s]",
acpi_ps_get_opcode_name(aml_opcode),
acpi_ut_get_descriptor_name(result_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
offset = (u32) offset_desc->integer.value;
/*
* Setup the Bit offsets and counts, according to the opcode
*/
switch (aml_opcode) {
case AML_CREATE_FIELD_OP:
/* Offset is in bits, count is in bits */
field_flags = AML_FIELD_ACCESS_BYTE;
bit_offset = offset;
bit_count = (u32) length_desc->integer.value;
/* Must have a valid (>0) bit count */
if (bit_count == 0) {
ACPI_ERROR((AE_INFO,
"Attempt to CreateField of length zero"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
break;
case AML_CREATE_BIT_FIELD_OP:
/* Offset is in bits, Field is one bit */
bit_offset = offset;
bit_count = 1;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
case AML_CREATE_BYTE_FIELD_OP:
/* Offset is in bytes, field is one byte */
bit_offset = 8 * offset;
bit_count = 8;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
case AML_CREATE_WORD_FIELD_OP:
/* Offset is in bytes, field is one word */
bit_offset = 8 * offset;
bit_count = 16;
field_flags = AML_FIELD_ACCESS_WORD;
break;
case AML_CREATE_DWORD_FIELD_OP:
/* Offset is in bytes, field is one dword */
bit_offset = 8 * offset;
bit_count = 32;
field_flags = AML_FIELD_ACCESS_DWORD;
break;
case AML_CREATE_QWORD_FIELD_OP:
/* Offset is in bytes, field is one qword */
bit_offset = 8 * offset;
bit_count = 64;
field_flags = AML_FIELD_ACCESS_QWORD;
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown field creation opcode 0x%02X",
aml_opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Entire field must fit within the current length of the buffer */
if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
ACPI_ERROR((AE_INFO,
"Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
acpi_ut_get_node_name(result_desc),
bit_offset + bit_count,
acpi_ut_get_node_name(buffer_desc->buffer.node),
8 * (u32) buffer_desc->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
/*
* Initialize areas of the field object that are common to all fields
* For field_flags, use LOCK_RULE = 0 (NO_LOCK),
* UPDATE_RULE = 0 (UPDATE_PRESERVE)
*/
status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
bit_offset, bit_count);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
obj_desc->buffer_field.buffer_obj = buffer_desc;
/* Reference count for buffer_desc inherits obj_desc count */
buffer_desc->common.reference_count = (u16)
(buffer_desc->common.reference_count +
obj_desc->common.reference_count);
cleanup:
/* Always delete the operands */
acpi_ut_remove_reference(offset_desc);
acpi_ut_remove_reference(buffer_desc);
if (aml_opcode == AML_CREATE_FIELD_OP) {
acpi_ut_remove_reference(length_desc);
}
/* On failure, delete the result descriptor */
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(result_desc); /* Result descriptor */
} else {
/* Now the address and length are valid for this buffer_field */
obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_buffer_field_operands
*
* PARAMETERS: walk_state - Current walk
* op - A valid buffer_field Op object
*
* RETURN: Status
*
* DESCRIPTION: Get buffer_field Buffer and Index
* Called from acpi_ds_exec_end_op during buffer_field parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
/*
* This is where we evaluate the address and length fields of the
* create_xxx_field declaration
*/
node = op->common.node;
/* next_op points to the op that holds the Buffer */
next_op = op->common.value.arg;
/* Evaluate/create the address and length operands */
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Resolve the operands */
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
acpi_ps_get_opcode_name(op->common.aml_opcode),
status));
return_ACPI_STATUS(status);
}
/* Initialize the Buffer Field */
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* NOTE: Slightly different operands for this opcode */
status =
acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
walk_state->operands[0],
walk_state->operands[1],
walk_state->operands[2],
walk_state->operands[3]);
} else {
/* All other, create_xxx_field opcodes */
status =
acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
walk_state->operands[0],
walk_state->operands[1], NULL,
walk_state->operands[2]);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_region_operands
*
* PARAMETERS: walk_state - Current walk
* op - A valid region Op object
*
* RETURN: Status
*
* DESCRIPTION: Get region address and length
* Called from acpi_ds_exec_end_op during op_region parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object *operand_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
/*
* This is where we evaluate the address and length fields of the
* op_region declaration
*/
node = op->common.node;
/* next_op points to the op that holds the space_ID */
next_op = op->common.value.arg;
/* next_op points to address op */
next_op = next_op->common.next;
/* Evaluate/create the address and length operands */
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Resolve the length and address operands to numbers */
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* Get the length operand and save it
* (at Top of stack)
*/
operand_desc = walk_state->operands[walk_state->num_operands - 1];
obj_desc->region.length = (u32) operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
/*
* Get the address and save it
* (at top of stack - 1)
*/
operand_desc = walk_state->operands[walk_state->num_operands - 2];
obj_desc->region.address = (acpi_physical_address)
operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_UINT64(obj_desc->region.address),
obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_table_region_operands
*
* PARAMETERS: walk_state - Current walk
* op - A valid region Op object
*
* RETURN: Status
*
* DESCRIPTION: Get region address and length.
* Called from acpi_ds_exec_end_op during data_table_region parse
* tree walk.
*
******************************************************************************/
acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object **operand;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
struct acpi_table_header *table;
u32 table_index;
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
/*
* This is where we evaluate the Signature string, oem_id string,
* and oem_table_id string of the Data Table Region declaration
*/
node = op->common.node;
/* next_op points to Signature string op */
next_op = op->common.value.arg;
/*
* Evaluate/create the Signature string, oem_id string,
* and oem_table_id string operands
*/
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
operand = &walk_state->operands[0];
/*
* Resolve the Signature string, oem_id string,
* and oem_table_id string operands
*/
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Find the ACPI table */
status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
ACPI_ERROR((AE_INFO,
"ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer));
}
goto cleanup;
}
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto cleanup;
}
obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
obj_desc->region.length = table->length;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_UINT64(obj_desc->region.address),
obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
cleanup:
acpi_ut_remove_reference(operand[0]);
acpi_ut_remove_reference(operand[1]);
acpi_ut_remove_reference(operand[2]);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_data_object_operands
*
* PARAMETERS: walk_state - Current walk
* op - A valid data_object Op object
* obj_desc - data_object
*
* RETURN: Status
*
* DESCRIPTION: Get the operands and complete the following data object types:
* Buffer, Package.
*
******************************************************************************/
acpi_status
acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
union acpi_operand_object *obj_desc)
{
acpi_status status;
union acpi_operand_object *arg_desc;
u32 length;
ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
/* The first operand (for all of these data objects) is the length */
/*
* Set proper index into operand stack for acpi_ds_obj_stack_push
* invoked inside acpi_ds_create_operand.
*/
walk_state->operand_index = walk_state->num_operands;
status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ex_resolve_operands(walk_state->opcode,
&(walk_state->
operands[walk_state->num_operands -
1]), walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Extract length operand */
arg_desc = walk_state->operands[walk_state->num_operands - 1];
length = (u32) arg_desc->integer.value;
/* Cleanup for length operand */
status = acpi_ds_obj_stack_pop(1, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_remove_reference(arg_desc);
/*
* Create the actual data object
*/
switch (op->common.aml_opcode) {
case AML_BUFFER_OP:
status =
acpi_ds_build_internal_buffer_obj(walk_state, op, length,
&obj_desc);
break;
case AML_PACKAGE_OP:
case AML_VAR_PACKAGE_OP:
status =
acpi_ds_build_internal_package_obj(walk_state, op, length,
&obj_desc);
break;
default:
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
if (ACPI_SUCCESS(status)) {
/*
* Return the object in the walk_state, unless the parent is a package -
* in this case, the return object will be stored in the parse tree
* for the package.
*/
if ((!op->common.parent) ||
((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
(op->common.parent->common.aml_opcode !=
AML_VAR_PACKAGE_OP)
&& (op->common.parent->common.aml_opcode !=
AML_NAME_OP))) {
walk_state->result_obj = obj_desc;
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_bank_field_operands
*
* PARAMETERS: walk_state - Current walk
* op - A valid bank_field Op object
*
* RETURN: Status
*
* DESCRIPTION: Get bank_field bank_value
* Called from acpi_ds_exec_end_op during bank_field parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object *operand_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
union acpi_parse_object *arg;
ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
/*
* This is where we evaluate the bank_value field of the
* bank_field declaration
*/
/* next_op points to the op that holds the Region */
next_op = op->common.value.arg;
/* next_op points to the op that holds the Bank Register */
next_op = next_op->common.next;
/* next_op points to the op that holds the Bank Value */
next_op = next_op->common.next;
/*
* Set proper index into operand stack for acpi_ds_obj_stack_push
* invoked inside acpi_ds_create_operand.
*
* We use walk_state->Operands[0] to store the evaluated bank_value
*/
walk_state->operand_index = 0;
status = acpi_ds_create_operand(walk_state, next_op, 0);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
/*
* Get the bank_value operand and save it
* (at Top of stack)
*/
operand_desc = walk_state->operands[0];
/* Arg points to the start Bank Field */
arg = acpi_ps_get_arg(op, 4);
while (arg) {
/* Ignore OFFSET and ACCESSAS terms here */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
node = arg->common.node;
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
obj_desc->bank_field.value =
(u32) operand_desc->integer.value;
}
/* Move to next field in the list */
arg = arg->common.next;
}
acpi_ut_remove_reference(operand_desc);
return_ACPI_STATUS(status);
}

View File

@@ -1,879 +0,0 @@
/*******************************************************************************
*
* Module Name: dsutils - Dispatcher utilities
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsutils")
/*******************************************************************************
*
* FUNCTION: acpi_ds_clear_implicit_return
*
* PARAMETERS: walk_state - Current State
*
* RETURN: None.
*
* DESCRIPTION: Clear and remove a reference on an implicit return value. Used
* to delete "stale" return values (if enabled, the return value
* from every operator is saved at least momentarily, in case the
* parent method exits.)
*
******************************************************************************/
void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
{
ACPI_FUNCTION_NAME(ds_clear_implicit_return);
/*
* Slack must be enabled for this feature
*/
if (!acpi_gbl_enable_interpreter_slack) {
return;
}
if (walk_state->implicit_return_obj) {
/*
* Delete any "stale" implicit return. However, in
* complex statements, the implicit return value can be
* bubbled up several levels.
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Removing reference on stale implicit return obj %p\n",
walk_state->implicit_return_obj));
acpi_ut_remove_reference(walk_state->implicit_return_obj);
walk_state->implicit_return_obj = NULL;
}
}
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
* FUNCTION: acpi_ds_do_implicit_return
*
* PARAMETERS: return_desc - The return value
* walk_state - Current State
* add_reference - True if a reference should be added to the
* return object
*
* RETURN: TRUE if implicit return enabled, FALSE otherwise
*
* DESCRIPTION: Implements the optional "implicit return". We save the result
* of every ASL operator and control method invocation in case the
* parent method exit. Before storing a new return value, we
* delete the previous return value.
*
******************************************************************************/
u8
acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
struct acpi_walk_state *walk_state, u8 add_reference)
{
ACPI_FUNCTION_NAME(ds_do_implicit_return);
/*
* Slack must be enabled for this feature, and we must
* have a valid return object
*/
if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
return (FALSE);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Result %p will be implicitly returned; Prev=%p\n",
return_desc, walk_state->implicit_return_obj));
/*
* Delete any "stale" implicit return value first. However, in
* complex statements, the implicit return value can be
* bubbled up several levels, so we don't clear the value if it
* is the same as the return_desc.
*/
if (walk_state->implicit_return_obj) {
if (walk_state->implicit_return_obj == return_desc) {
return (TRUE);
}
acpi_ds_clear_implicit_return(walk_state);
}
/* Save the implicit return value, add a reference if requested */
walk_state->implicit_return_obj = return_desc;
if (add_reference) {
acpi_ut_add_reference(return_desc);
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_is_result_used
*
* PARAMETERS: op - Current Op
* walk_state - Current State
*
* RETURN: TRUE if result is used, FALSE otherwise
*
* DESCRIPTION: Check if a result object will be used by the parent
*
******************************************************************************/
u8
acpi_ds_is_result_used(union acpi_parse_object * op,
struct acpi_walk_state * walk_state)
{
const struct acpi_opcode_info *parent_info;
ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
/* Must have both an Op and a Result Object */
if (!op) {
ACPI_ERROR((AE_INFO, "Null Op"));
return_UINT8(TRUE);
}
/*
* We know that this operator is not a
* Return() operator (would not come here.) The following code is the
* optional support for a so-called "implicit return". Some AML code
* assumes that the last value of the method is "implicitly" returned
* to the caller. Just save the last result as the return value.
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
(void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
TRUE);
/*
* Now determine if the parent will use the result
*
* If there is no parent, or the parent is a scope_op, we are executing
* at the method level. An executing method typically has no parent,
* since each method is parsed separately. A method invoked externally
* via execute_control_method has a scope_op as the parent.
*/
if ((!op->common.parent) ||
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
/* No parent, the return value cannot possibly be used */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"At Method level, result of [%s] not used\n",
acpi_ps_get_opcode_name(op->common.
aml_opcode)));
return_UINT8(FALSE);
}
/* Get info on the parent. The root_op is AML_SCOPE */
parent_info =
acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
if (parent_info->class == AML_CLASS_UNKNOWN) {
ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
return_UINT8(FALSE);
}
/*
* Decide what to do with the result based on the parent. If
* the parent opcode will not use the result, delete the object.
* Otherwise leave it as is, it will be deleted when it is used
* as an operand later.
*/
switch (parent_info->class) {
case AML_CLASS_CONTROL:
switch (op->common.parent->common.aml_opcode) {
case AML_RETURN_OP:
/* Never delete the return value associated with a return opcode */
goto result_used;
case AML_IF_OP:
case AML_WHILE_OP:
/*
* If we are executing the predicate AND this is the predicate op,
* we will use the return value
*/
if ((walk_state->control_state->common.state ==
ACPI_CONTROL_PREDICATE_EXECUTING)
&& (walk_state->control_state->control.
predicate_op == op)) {
goto result_used;
}
break;
default:
/* Ignore other control opcodes */
break;
}
/* The general control opcode returns no result */
goto result_not_used;
case AML_CLASS_CREATE:
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
*/
goto result_used;
case AML_CLASS_NAMED_OBJECT:
if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
(op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
|| (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
|| (op->common.parent->common.aml_opcode ==
AML_VAR_PACKAGE_OP)
|| (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
|| (op->common.parent->common.aml_opcode ==
AML_INT_EVAL_SUBTREE_OP)
|| (op->common.parent->common.aml_opcode ==
AML_BANK_FIELD_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
*/
goto result_used;
}
goto result_not_used;
default:
/*
* In all other cases. the parent will actually use the return
* object, so keep it.
*/
goto result_used;
}
result_used:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Result of [%s] used by Parent [%s] Op=%p\n",
acpi_ps_get_opcode_name(op->common.aml_opcode),
acpi_ps_get_opcode_name(op->common.parent->common.
aml_opcode), op));
return_UINT8(TRUE);
result_not_used:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Result of [%s] not used by Parent [%s] Op=%p\n",
acpi_ps_get_opcode_name(op->common.aml_opcode),
acpi_ps_get_opcode_name(op->common.parent->common.
aml_opcode), op));
return_UINT8(FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_result_if_not_used
*
* PARAMETERS: op - Current parse Op
* result_obj - Result of the operation
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Used after interpretation of an opcode. If there is an internal
* result descriptor, check if the parent opcode will actually use
* this result. If not, delete the result now so that it will
* not become orphaned.
*
******************************************************************************/
void
acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
union acpi_operand_object *result_obj,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *obj_desc;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
if (!op) {
ACPI_ERROR((AE_INFO, "Null Op"));
return_VOID;
}
if (!result_obj) {
return_VOID;
}
if (!acpi_ds_is_result_used(op, walk_state)) {
/* Must pop the result stack (obj_desc should be equal to result_obj) */
status = acpi_ds_result_pop(&obj_desc, walk_state);
if (ACPI_SUCCESS(status)) {
acpi_ut_remove_reference(result_obj);
}
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_resolve_operands
*
* PARAMETERS: walk_state - Current walk state with operands on stack
*
* RETURN: Status
*
* DESCRIPTION: Resolve all operands to their values. Used to prepare
* arguments to a control method invocation (a call from one
* method to another.)
*
******************************************************************************/
acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
{
u32 i;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
/*
* Attempt to resolve each of the valid operands
* Method arguments are passed by reference, not by value. This means
* that the actual objects are passed, not copies of the objects.
*/
for (i = 0; i < walk_state->num_operands; i++) {
status =
acpi_ex_resolve_to_value(&walk_state->operands[i],
walk_state);
if (ACPI_FAILURE(status)) {
break;
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_clear_operands
*
* PARAMETERS: walk_state - Current walk state with operands on stack
*
* RETURN: None
*
* DESCRIPTION: Clear all operands on the current walk state operand stack.
*
******************************************************************************/
void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
{
u32 i;
ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
/* Remove a reference on each operand on the stack */
for (i = 0; i < walk_state->num_operands; i++) {
/*
* Remove a reference to all operands, including both
* "Arguments" and "Targets".
*/
acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
walk_state->num_operands = 0;
return_VOID;
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operand
*
* PARAMETERS: walk_state - Current walk state
* arg - Parse object for the argument
* arg_index - Which argument (zero based)
*
* RETURN: Status
*
* DESCRIPTION: Translate a parse tree object that is an argument to an AML
* opcode to the equivalent interpreter object. This may include
* looking up a name or entering a new name into the internal
* namespace.
*
******************************************************************************/
acpi_status
acpi_ds_create_operand(struct acpi_walk_state *walk_state,
union acpi_parse_object *arg, u32 arg_index)
{
acpi_status status = AE_OK;
char *name_string;
u32 name_length;
union acpi_operand_object *obj_desc;
union acpi_parse_object *parent_op;
u16 opcode;
acpi_interpreter_mode interpreter_mode;
const struct acpi_opcode_info *op_info;
ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
/* A valid name must be looked up in the namespace */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
(arg->common.value.string) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
arg));
/* Get the entire name string from the AML stream */
status =
acpi_ex_get_name_string(ACPI_TYPE_ANY,
arg->common.value.buffer,
&name_string, &name_length);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* All prefixes have been handled, and the name is in name_string */
/*
* Special handling for buffer_field declarations. This is a deferred
* opcode that unfortunately defines the field name as the last
* parameter instead of the first. We get here when we are performing
* the deferred execution, so the actual name of the field is already
* in the namespace. We don't want to attempt to look it up again
* because we may be executing in a different scope than where the
* actual opcode exists.
*/
if ((walk_state->deferred_node) &&
(walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
&& (arg_index ==
(u32) ((walk_state->opcode ==
AML_CREATE_FIELD_OP) ? 3 : 2))) {
obj_desc =
ACPI_CAST_PTR(union acpi_operand_object,
walk_state->deferred_node);
status = AE_OK;
} else { /* All other opcodes */
/*
* Differentiate between a namespace "create" operation
* versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
* IMODE_EXECUTE) in order to support the creation of
* namespace objects during the execution of control methods.
*/
parent_op = arg->common.parent;
op_info =
acpi_ps_get_opcode_info(parent_op->common.
aml_opcode);
if ((op_info->flags & AML_NSNODE)
&& (parent_op->common.aml_opcode !=
AML_INT_METHODCALL_OP)
&& (parent_op->common.aml_opcode != AML_REGION_OP)
&& (parent_op->common.aml_opcode !=
AML_INT_NAMEPATH_OP)) {
/* Enter name into namespace if not found */
interpreter_mode = ACPI_IMODE_LOAD_PASS2;
} else {
/* Return a failure if name not found */
interpreter_mode = ACPI_IMODE_EXECUTE;
}
status =
acpi_ns_lookup(walk_state->scope_info, name_string,
ACPI_TYPE_ANY, interpreter_mode,
ACPI_NS_SEARCH_PARENT |
ACPI_NS_DONT_OPEN_SCOPE, walk_state,
ACPI_CAST_INDIRECT_PTR(struct
acpi_namespace_node,
&obj_desc));
/*
* The only case where we pass through (ignore) a NOT_FOUND
* error is for the cond_ref_of opcode.
*/
if (status == AE_NOT_FOUND) {
if (parent_op->common.aml_opcode ==
AML_COND_REF_OF_OP) {
/*
* For the Conditional Reference op, it's OK if
* the name is not found; We just need a way to
* indicate this to the interpreter, set the
* object to the root
*/
obj_desc =
ACPI_CAST_PTR(union
acpi_operand_object,
acpi_gbl_root_node);
status = AE_OK;
} else if (parent_op->common.aml_opcode ==
AML_EXTERNAL_OP) {
/* TBD: May only be temporary */
obj_desc =
acpi_ut_create_string_object((acpi_size) name_length);
strncpy(obj_desc->string.pointer,
name_string, name_length);
status = AE_OK;
} else {
/*
* We just plain didn't find it -- which is a
* very serious error at this point
*/
status = AE_AML_NAME_NOT_FOUND;
}
}
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(name_string, status);
}
}
/* Free the namestring created above */
ACPI_FREE(name_string);
/* Check status from the lookup */
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Put the resulting object onto the current object stack */
status = acpi_ds_obj_stack_push(obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
(obj_desc, walk_state));
} else {
/* Check for null name case */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
/*
* If the name is null, this means that this is an
* optional result parameter that was not specified
* in the original ASL. Create a Zero Constant for a
* placeholder. (Store to a constant is a Noop.)
*/
opcode = AML_ZERO_OP; /* Has no arguments! */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Null namepath: Arg=%p\n", arg));
} else {
opcode = arg->common.aml_opcode;
}
/* Get the object type of the argument */
op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->object_type == ACPI_TYPE_INVALID) {
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
if ((op_info->flags & AML_HAS_RETVAL)
|| (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Argument previously created, already stacked\n"));
ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
(walk_state->
operands[walk_state->num_operands -
1], walk_state));
/*
* Use value that was already previously returned
* by the evaluation of this argument
*/
status = acpi_ds_result_pop(&obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
/*
* Only error is underflow, and this indicates
* a missing or null operand!
*/
ACPI_EXCEPTION((AE_INFO, status,
"Missing or null operand"));
return_ACPI_STATUS(status);
}
} else {
/* Create an ACPI_INTERNAL_OBJECT for the argument */
obj_desc =
acpi_ut_create_internal_object(op_info->
object_type);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new object */
status =
acpi_ds_init_object_from_op(walk_state, arg, opcode,
&obj_desc);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(status);
}
}
/* Put the operand object on the object stack */
status = acpi_ds_obj_stack_push(obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
(obj_desc, walk_state));
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operands
*
* PARAMETERS: walk_state - Current state
* first_arg - First argument of a parser argument tree
*
* RETURN: Status
*
* DESCRIPTION: Convert an operator's arguments from a parse tree format to
* namespace objects and place those argument object on the object
* stack in preparation for evaluation by the interpreter.
*
******************************************************************************/
acpi_status
acpi_ds_create_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *first_arg)
{
acpi_status status = AE_OK;
union acpi_parse_object *arg;
union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
u32 arg_count = 0;
u32 index = walk_state->num_operands;
u32 i;
ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
/* Get all arguments in the list */
arg = first_arg;
while (arg) {
if (index >= ACPI_OBJ_NUM_OPERANDS) {
return_ACPI_STATUS(AE_BAD_DATA);
}
arguments[index] = arg;
walk_state->operands[index] = NULL;
/* Move on to next argument, if any */
arg = arg->common.next;
arg_count++;
index++;
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"NumOperands %d, ArgCount %d, Index %d\n",
walk_state->num_operands, arg_count, index));
/* Create the interpreter arguments, in reverse order */
index--;
for (i = 0; i < arg_count; i++) {
arg = arguments[index];
walk_state->operand_index = (u8)index;
status = acpi_ds_create_operand(walk_state, arg, index);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Created Arg #%u (%p) %u args total\n",
index, arg, arg_count));
index--;
}
return_ACPI_STATUS(status);
cleanup:
/*
* We must undo everything done above; meaning that we must
* pop everything off of the operand stack and delete those
* objects
*/
acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
return_ACPI_STATUS(status);
}
/*****************************************************************************
*
* FUNCTION: acpi_ds_evaluate_name_path
*
* PARAMETERS: walk_state - Current state of the parse tree walk,
* the opcode of current operation should be
* AML_INT_NAMEPATH_OP
*
* RETURN: Status
*
* DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
* interpreter object, convert it to value, if needed, duplicate
* it, if needed, and push it onto the current result stack.
*
****************************************************************************/
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_parse_object *op = walk_state->op;
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *new_obj_desc;
u8 type;
ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
if (!op->common.parent) {
/* This happens after certain exception processing */
goto exit;
}
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
/* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
goto exit;
}
status = acpi_ds_create_operand(walk_state, op, 0);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (op->common.flags & ACPI_PARSEOP_TARGET) {
new_obj_desc = *operand;
goto push_result;
}
type = (*operand)->common.type;
status = acpi_ex_resolve_to_value(operand, walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (type == ACPI_TYPE_INTEGER) {
/* It was incremented by acpi_ex_resolve_to_value */
acpi_ut_remove_reference(*operand);
status =
acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
} else {
/*
* The object either was anew created or is
* a Namespace node - don't decrement it.
*/
new_obj_desc = *operand;
}
/* Cleanup for name-path operand */
status = acpi_ds_obj_stack_pop(1, walk_state);
if (ACPI_FAILURE(status)) {
walk_state->result_obj = new_obj_desc;
goto exit;
}
push_result:
walk_state->result_obj = new_obj_desc;
status = acpi_ds_result_push(walk_state->result_obj, walk_state);
if (ACPI_SUCCESS(status)) {
/* Force to take it from stack */
op->common.flags |= ACPI_PARSEOP_IN_STACK;
}
exit:
return_ACPI_STATUS(status);
}

View File

@@ -1,759 +0,0 @@
/******************************************************************************
*
* Module Name: dswexec - Dispatcher method execution callbacks;
* dispatch to interpreter.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswexec")
/*
* Dispatch table for opcode classes
*/
static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
acpi_ex_opcode_0A_0T_1R,
acpi_ex_opcode_1A_0T_0R,
acpi_ex_opcode_1A_0T_1R,
acpi_ex_opcode_1A_1T_0R,
acpi_ex_opcode_1A_1T_1R,
acpi_ex_opcode_2A_0T_0R,
acpi_ex_opcode_2A_0T_1R,
acpi_ex_opcode_2A_1T_1R,
acpi_ex_opcode_2A_2T_1R,
acpi_ex_opcode_3A_0T_0R,
acpi_ex_opcode_3A_1T_1R,
acpi_ex_opcode_6A_0T_1R
};
/*****************************************************************************
*
* FUNCTION: acpi_ds_get_predicate_value
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* result_obj - if non-zero, pop result from result stack
*
* RETURN: Status
*
* DESCRIPTION: Get the result of a predicate evaluation
*
****************************************************************************/
acpi_status
acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
union acpi_operand_object *result_obj)
{
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
union acpi_operand_object *local_obj_desc = NULL;
ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state);
walk_state->control_state->common.state = 0;
if (result_obj) {
status = acpi_ds_result_pop(&obj_desc, walk_state);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not get result from predicate evaluation"));
return_ACPI_STATUS(status);
}
} else {
status = acpi_ds_create_operand(walk_state, walk_state->op, 0);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status =
acpi_ex_resolve_to_value(&walk_state->operands[0],
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = walk_state->operands[0];
}
if (!obj_desc) {
ACPI_ERROR((AE_INFO,
"No predicate ObjDesc=%p State=%p",
obj_desc, walk_state));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
* Result of predicate evaluation must be an Integer
* object. Implicitly convert the argument if necessary.
*/
status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X",
obj_desc, walk_state, obj_desc->common.type));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
/* Truncate the predicate to 32-bits if necessary */
(void)acpi_ex_truncate_for32bit_table(local_obj_desc);
/*
* Save the result of the predicate evaluation on
* the control stack
*/
if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
} else {
/*
* Predicate is FALSE, we will just toss the
* rest of the package
*/
walk_state->control_state->common.value = FALSE;
status = AE_CTRL_FALSE;
}
/* Predicate can be used for an implicit return value */
(void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
cleanup:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
walk_state->control_state->common.value,
walk_state->op));
/* Break to debugger to display result */
ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
(local_obj_desc, walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
if (local_obj_desc != obj_desc) {
acpi_ut_remove_reference(local_obj_desc);
}
acpi_ut_remove_reference(obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
return_ACPI_STATUS(status);
}
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* out_op - Where to return op if a new one is created
*
* RETURN: Status
*
* DESCRIPTION: Descending callback used during the execution of control
* methods. This is where most operators and operands are
* dispatched to the interpreter.
*
****************************************************************************/
acpi_status
acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op)
{
union acpi_parse_object *op;
acpi_status status = AE_OK;
u32 opcode_class;
ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state);
op = walk_state->op;
if (!op) {
status = acpi_ds_load2_begin_op(walk_state, out_op);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
op = *out_op;
walk_state->op = op;
walk_state->opcode = op->common.aml_opcode;
walk_state->op_info =
acpi_ps_get_opcode_info(op->common.aml_opcode);
if (acpi_ns_opens_scope(walk_state->op_info->object_type)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"(%s) Popping scope for Op %p\n",
acpi_ut_get_type_name(walk_state->
op_info->
object_type),
op));
status = acpi_ds_scope_stack_pop(walk_state);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
}
}
if (op == walk_state->origin) {
if (out_op) {
*out_op = op;
}
return_ACPI_STATUS(AE_OK);
}
/*
* If the previous opcode was a conditional, this opcode
* must be the beginning of the associated predicate.
* Save this knowledge in the current scope descriptor
*/
if ((walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Exec predicate Op=%p State=%p\n", op,
walk_state));
walk_state->control_state->common.state =
ACPI_CONTROL_PREDICATE_EXECUTING;
/* Save start of predicate */
walk_state->control_state->control.predicate_op = op;
}
opcode_class = walk_state->op_info->class;
/* We want to send namepaths to the load code */
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
opcode_class = AML_CLASS_NAMED_OBJECT;
}
/*
* Handle the opcode based upon the opcode type
*/
switch (opcode_class) {
case AML_CLASS_CONTROL:
status = acpi_ds_exec_begin_control_op(walk_state, op);
break;
case AML_CLASS_NAMED_OBJECT:
if (walk_state->walk_type & ACPI_WALK_METHOD) {
/*
* Found a named object declaration during method execution;
* we must enter this object into the namespace. The created
* object is temporary and will be deleted upon completion of
* the execution of this method.
*
* Note 10/2010: Except for the Scope() op. This opcode does
* not actually create a new object, it refers to an existing
* object. However, for Scope(), we want to indeed open a
* new scope.
*/
if (op->common.aml_opcode != AML_SCOPE_OP) {
status =
acpi_ds_load2_begin_op(walk_state, NULL);
} else {
status =
acpi_ds_scope_stack_push(op->named.node,
op->named.node->
type, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
break;
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
break;
default:
break;
}
/* Nothing to do here during method execution */
return_ACPI_STATUS(status);
error_exit:
status = acpi_ds_method_error(status, walk_state);
return_ACPI_STATUS(status);
}
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_end_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
*
* RETURN: Status
*
* DESCRIPTION: Ascending callback used during the execution of control
* methods. The only thing we really need to do here is to
* notice the beginning of IF, ELSE, and WHILE blocks.
*
****************************************************************************/
acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
{
union acpi_parse_object *op;
acpi_status status = AE_OK;
u32 op_type;
u32 op_class;
union acpi_parse_object *next_op;
union acpi_parse_object *first_arg;
ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
op = walk_state->op;
op_type = walk_state->op_info->type;
op_class = walk_state->op_info->class;
if (op_class == AML_CLASS_UNKNOWN) {
ACPI_ERROR((AE_INFO, "Unknown opcode 0x%X",
op->common.aml_opcode));
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
first_arg = op->common.value.arg;
/* Init the walk state */
walk_state->num_operands = 0;
walk_state->operand_index = 0;
walk_state->return_desc = NULL;
walk_state->result_obj = NULL;
/* Call debugger for single step support (DEBUG build only) */
ACPI_DEBUGGER_EXEC(status =
acpi_db_single_step(walk_state, op, op_class));
ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);}
) ;
/* Decode the Opcode Class */
switch (op_class) {
case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
status = acpi_ds_evaluate_name_path(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
break;
case AML_CLASS_EXECUTE: /* Most operators with arguments */
/* Build resolved operand stack */
status = acpi_ds_create_operands(walk_state, first_arg);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* All opcodes require operand resolution, with the only exceptions
* being the object_type and size_of operators.
*/
if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
/* Resolve all operands */
status = acpi_ex_resolve_operands(walk_state->opcode,
&(walk_state->
operands
[walk_state->
num_operands - 1]),
walk_state);
}
if (ACPI_SUCCESS(status)) {
/*
* Dispatch the request to the appropriate interpreter handler
* routine. There is one routine per opcode "type" based upon the
* number of opcode arguments and return type.
*/
status =
acpi_gbl_op_type_dispatch[op_type] (walk_state);
} else {
/*
* Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
* Local is uninitialized.
*/
if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
(walk_state->opcode == AML_STORE_OP) &&
(walk_state->operands[0]->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
&& (walk_state->operands[1]->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
&& (walk_state->operands[0]->reference.class ==
walk_state->operands[1]->reference.class)
&& (walk_state->operands[0]->reference.value ==
walk_state->operands[1]->reference.value)) {
status = AE_OK;
} else {
ACPI_EXCEPTION((AE_INFO, status,
"While resolving operands for [%s]",
acpi_ps_get_opcode_name
(walk_state->opcode)));
}
}
/* Always delete the argument objects and clear the operand stack */
acpi_ds_clear_operands(walk_state);
/*
* If a result object was returned from above, push it on the
* current result stack
*/
if (ACPI_SUCCESS(status) && walk_state->result_obj) {
status =
acpi_ds_result_push(walk_state->result_obj,
walk_state);
}
break;
default:
switch (op_type) {
case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
/* 1 Operand, 0 external_result, 0 internal_result */
status = acpi_ds_exec_end_control_op(walk_state, op);
break;
case AML_TYPE_METHOD_CALL:
/*
* If the method is referenced from within a package
* declaration, it is not a invocation of the method, just
* a reference to it.
*/
if ((op->asl.parent) &&
((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
|| (op->asl.parent->asl.aml_opcode ==
AML_VAR_PACKAGE_OP))) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Method Reference in a Package, Op=%p\n",
op));
op->common.node =
(struct acpi_namespace_node *)op->asl.value.
arg->asl.node;
acpi_ut_add_reference(op->asl.value.arg->asl.
node->object);
return_ACPI_STATUS(AE_OK);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Method invocation, Op=%p\n", op));
/*
* (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
* the method Node pointer
*/
/* next_op points to the op that holds the method name */
next_op = first_arg;
/* next_op points to first argument op */
next_op = next_op->common.next;
/*
* Get the method's arguments and put them on the operand stack
*/
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
break;
}
/*
* Since the operands will be passed to another control method,
* we must resolve all local references here (Local variables,
* arguments to *this* method, etc.)
*/
status = acpi_ds_resolve_operands(walk_state);
if (ACPI_FAILURE(status)) {
/* On error, clear all resolved operands */
acpi_ds_clear_operands(walk_state);
break;
}
/*
* Tell the walk loop to preempt this running method and
* execute the new method
*/
status = AE_CTRL_TRANSFER;
/*
* Return now; we don't want to disturb anything,
* especially the operand count!
*/
return_ACPI_STATUS(status);
case AML_TYPE_CREATE_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing CreateField Buffer/Index Op=%p\n",
op));
status = acpi_ds_load2_end_op(walk_state);
if (ACPI_FAILURE(status)) {
break;
}
status =
acpi_ds_eval_buffer_field_operands(walk_state, op);
break;
case AML_TYPE_CREATE_OBJECT:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing CreateObject (Buffer/Package) Op=%p\n",
op));
switch (op->common.parent->common.aml_opcode) {
case AML_NAME_OP:
/*
* Put the Node on the object stack (Contains the ACPI Name
* of this object)
*/
walk_state->operands[0] =
(void *)op->common.parent->common.node;
walk_state->num_operands = 1;
status = acpi_ds_create_node(walk_state,
op->common.parent->
common.node,
op->common.parent);
if (ACPI_FAILURE(status)) {
break;
}
/* Fall through */
/*lint -fallthrough */
case AML_INT_EVAL_SUBTREE_OP:
status =
acpi_ds_eval_data_object_operands
(walk_state, op,
acpi_ns_get_attached_object(op->common.
parent->common.
node));
break;
default:
status =
acpi_ds_eval_data_object_operands
(walk_state, op, NULL);
break;
}
/*
* If a result object was returned from above, push it on the
* current result stack
*/
if (walk_state->result_obj) {
status =
acpi_ds_result_push(walk_state->result_obj,
walk_state);
}
break;
case AML_TYPE_NAMED_FIELD:
case AML_TYPE_NAMED_COMPLEX:
case AML_TYPE_NAMED_SIMPLE:
case AML_TYPE_NAMED_NO_OBJ:
status = acpi_ds_load2_end_op(walk_state);
if (ACPI_FAILURE(status)) {
break;
}
if (op->common.aml_opcode == AML_REGION_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing OpRegion Address/Length Op=%p\n",
op));
status =
acpi_ds_eval_region_operands(walk_state,
op);
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing DataTableRegion Strings Op=%p\n",
op));
status =
acpi_ds_eval_table_region_operands
(walk_state, op);
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing BankField Op=%p\n",
op));
status =
acpi_ds_eval_bank_field_operands(walk_state,
op);
if (ACPI_FAILURE(status)) {
break;
}
}
break;
case AML_TYPE_UNDEFINED:
ACPI_ERROR((AE_INFO,
"Undefined opcode type Op=%p", op));
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
case AML_TYPE_BOGUS:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Internal opcode=%X type Op=%p\n",
walk_state->opcode, op));
break;
default:
ACPI_ERROR((AE_INFO,
"Unimplemented opcode, class=0x%X type=0x%X Opcode=0x%X Op=%p",
op_class, op_type, op->common.aml_opcode,
op));
status = AE_NOT_IMPLEMENTED;
break;
}
}
/*
* ACPI 2.0 support for 64-bit integers: Truncate numeric
* result value if we are executing from a 32-bit ACPI table
*/
(void)acpi_ex_truncate_for32bit_table(walk_state->result_obj);
/*
* Check if we just completed the evaluation of a
* conditional predicate
*/
if ((ACPI_SUCCESS(status)) &&
(walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_PREDICATE_EXECUTING) &&
(walk_state->control_state->control.predicate_op == op)) {
status =
acpi_ds_get_predicate_value(walk_state,
walk_state->result_obj);
walk_state->result_obj = NULL;
}
cleanup:
if (walk_state->result_obj) {
/* Break to debugger to display result */
ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
(walk_state->result_obj, walk_state));
/*
* Delete the result op if and only if:
* Parent will not use the result -- such as any
* non-nested type2 op in a method (parent will be method)
*/
acpi_ds_delete_result_if_not_used(op, walk_state->result_obj,
walk_state);
}
#ifdef _UNDER_DEVELOPMENT
if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
acpi_db_method_end(walk_state);
}
#endif
/* Invoke exception handler on error */
if (ACPI_FAILURE(status)) {
status = acpi_ds_method_error(status, walk_state);
}
/* Always clear the object stack */
walk_state->num_operands = 0;
return_ACPI_STATUS(status);
}

View File

@@ -1,579 +0,0 @@
/******************************************************************************
*
* Module Name: dswload - Dispatcher first pass namespace load callbacks
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#ifdef ACPI_ASL_COMPILER
#include "acdisasm.h"
#endif
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswload")
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_callbacks
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* pass_number - 1, 2, or 3
*
* RETURN: Status
*
* DESCRIPTION: Init walk state callbacks
*
******************************************************************************/
acpi_status
acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
{
switch (pass_number) {
case 0:
/* Parse only - caller will setup callbacks */
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;
walk_state->descending_callback = NULL;
walk_state->ascending_callback = NULL;
break;
case 1:
/* Load pass 1 */
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load1_begin_op;
walk_state->ascending_callback = acpi_ds_load1_end_op;
break;
case 2:
/* Load pass 2 */
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load2_begin_op;
walk_state->ascending_callback = acpi_ds_load2_end_op;
break;
case 3:
/* Execution pass */
#ifndef ACPI_NO_METHOD_EXECUTION
walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_exec_begin_op;
walk_state->ascending_callback = acpi_ds_exec_end_op;
#endif
break;
default:
return (AE_BAD_PARAMETER);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_begin_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* out_op - Where to return op if a new one is created
*
* RETURN: Status
*
* DESCRIPTION: Descending callback used during the loading of ACPI tables.
*
******************************************************************************/
acpi_status
acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
union acpi_parse_object ** out_op)
{
union acpi_parse_object *op;
struct acpi_namespace_node *node;
acpi_status status;
acpi_object_type object_type;
char *path;
u32 flags;
ACPI_FUNCTION_TRACE(ds_load1_begin_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
walk_state));
/* We are only interested in opcodes that have an associated name */
if (op) {
if (!(walk_state->op_info->flags & AML_NAMED)) {
*out_op = op;
return_ACPI_STATUS(AE_OK);
}
/* Check if this object has already been installed in the namespace */
if (op->common.node) {
*out_op = op;
return_ACPI_STATUS(AE_OK);
}
}
path = acpi_ps_get_next_namestring(&walk_state->parser_state);
/* Map the raw opcode into an internal object type */
object_type = walk_state->op_info->object_type;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"State=%p Op=%p [%s]\n", walk_state, op,
acpi_ut_get_type_name(object_type)));
switch (walk_state->opcode) {
case AML_SCOPE_OP:
/*
* The target name of the Scope() operator must exist at this point so
* that we can actually open the scope to enter new names underneath it.
* Allow search-to-root for single namesegs.
*/
status =
acpi_ns_lookup(walk_state->scope_info, path, object_type,
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
walk_state, &(node));
#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
/*
* Table disassembly:
* Target of Scope() not found. Generate an External for it, and
* insert the name into the namespace.
*/
acpi_dm_add_op_to_external_list(op, path,
ACPI_TYPE_DEVICE, 0, 0);
status =
acpi_ns_lookup(walk_state->scope_info, path,
object_type, ACPI_IMODE_LOAD_PASS1,
ACPI_NS_SEARCH_PARENT, walk_state,
&node);
}
#endif
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(path, status);
return_ACPI_STATUS(status);
}
/*
* Check to make sure that the target is
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
case ACPI_TYPE_ANY:
case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
/* These are acceptable types */
break;
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/*
* These types we will allow, but we will change the type.
* This enables some existing code of the form:
*
* Name (DEB, 0)
* Scope (DEB) { ... }
*
* Note: silently change the type here. On the second pass,
* we will report a warning
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Type override - [%4.4s] had invalid type (%s) "
"for Scope operator, changed to type ANY\n",
acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
break;
case ACPI_TYPE_METHOD:
/*
* Allow scope change to root during execution of module-level
* code. Root is typed METHOD during this time.
*/
if ((node == acpi_gbl_root_node) &&
(walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
break;
}
/*lint -fallthrough */
default:
/* All other types are an error */
ACPI_ERROR((AE_INFO,
"Invalid type (%s) for target of "
"Scope operator [%4.4s] (Cannot override)",
acpi_ut_get_type_name(node->type),
acpi_ut_get_node_name(node)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
default:
/*
* For all other named opcodes, we will enter the name into
* the namespace.
*
* Setup the search flags.
* Since we are entering a name into the namespace, we do not want to
* enable the search-to-root upsearch.
*
* There are only two conditions where it is acceptable that the name
* already exists:
* 1) the Scope() operator can reopen a scoping object that was
* previously defined (Scope, Method, Device, etc.)
* 2) Whenever we are parsing a deferred opcode (op_region, Buffer,
* buffer_field, or Package), the name of the object is already
* in the namespace.
*/
if (walk_state->deferred_node) {
/* This name is already in the namespace, get the node */
node = walk_state->deferred_node;
status = AE_OK;
break;
}
/*
* If we are executing a method, do not create any namespace objects
* during the load phase, only during execution.
*/
if (walk_state->method_node) {
node = NULL;
status = AE_OK;
break;
}
flags = ACPI_NS_NO_UPSEARCH;
if ((walk_state->opcode != AML_SCOPE_OP) &&
(!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
if (walk_state->namespace_override) {
flags |= ACPI_NS_OVERRIDE_IF_FOUND;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[%s] Override allowed\n",
acpi_ut_get_type_name
(object_type)));
} else {
flags |= ACPI_NS_ERROR_IF_FOUND;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[%s] Cannot already exist\n",
acpi_ut_get_type_name
(object_type)));
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[%s] Both Find or Create allowed\n",
acpi_ut_get_type_name(object_type)));
}
/*
* Enter the named type into the internal namespace. We enter the name
* as we go downward in the parse tree. Any necessary subobjects that
* involve arguments to the opcode must be created as we go back up the
* parse tree later.
*/
status =
acpi_ns_lookup(walk_state->scope_info, path, object_type,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&node);
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
/* The name already exists in this scope */
if (node->flags & ANOBJ_IS_EXTERNAL) {
/*
* Allow one create on an object or segment that was
* previously declared External
*/
node->flags &= ~ANOBJ_IS_EXTERNAL;
node->type = (u8) object_type;
/* Just retyped a node, probably will need to open a scope */
if (acpi_ns_opens_scope(object_type)) {
status =
acpi_ds_scope_stack_push
(node, object_type,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS
(status);
}
}
status = AE_OK;
}
}
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(path, status);
return_ACPI_STATUS(status);
}
}
break;
}
/* Common exit */
if (!op) {
/* Create a new op */
op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
}
/* Initialize the op */
#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
op->named.path = ACPI_CAST_PTR(u8, path);
#endif
if (node) {
/*
* Put the Node in the "op" object that the parser uses, so we
* can get it again quickly when this scope is closed
*/
op->common.node = node;
op->named.name = node->name.integer;
}
acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
op);
*out_op = op;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_end_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
*
* RETURN: Status
*
* DESCRIPTION: Ascending callback used during the loading of the namespace,
* both control methods and everything else.
*
******************************************************************************/
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
{
union acpi_parse_object *op;
acpi_object_type object_type;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ds_load1_end_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
walk_state));
/* We are only interested in opcodes that have an associated name */
if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
return_ACPI_STATUS(AE_OK);
}
/* Get the object type to determine if we should pop the scope */
object_type = walk_state->op_info->object_type;
#ifndef ACPI_NO_METHOD_EXECUTION
if (walk_state->op_info->flags & AML_FIELD) {
/*
* If we are executing a method, do not create any namespace objects
* during the load phase, only during execution.
*/
if (!walk_state->method_node) {
if (walk_state->opcode == AML_FIELD_OP ||
walk_state->opcode == AML_BANK_FIELD_OP ||
walk_state->opcode == AML_INDEX_FIELD_OP) {
status =
acpi_ds_init_field_objects(op, walk_state);
}
}
return_ACPI_STATUS(status);
}
/*
* If we are executing a method, do not create any namespace objects
* during the load phase, only during execution.
*/
if (!walk_state->method_node) {
if (op->common.aml_opcode == AML_REGION_OP) {
status =
acpi_ex_create_region(op->named.data,
op->named.length,
(acpi_adr_space_type) ((op->
common.
value.
arg)->
common.
value.
integer),
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
status =
acpi_ex_create_region(op->named.data,
op->named.length,
ACPI_ADR_SPACE_DATA_TABLE,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
#endif
if (op->common.aml_opcode == AML_NAME_OP) {
/* For Name opcode, get the object type from the argument */
if (op->common.value.arg) {
object_type = (acpi_ps_get_opcode_info((op->common.
value.arg)->
common.
aml_opcode))->
object_type;
/* Set node type if we have a namespace node */
if (op->common.node) {
op->common.node->type = (u8) object_type;
}
}
}
/*
* If we are executing a method, do not create any namespace objects
* during the load phase, only during execution.
*/
if (!walk_state->method_node) {
if (op->common.aml_opcode == AML_METHOD_OP) {
/*
* method_op pkg_length name_string method_flags term_list
*
* Note: We must create the method node/object pair as soon as we
* see the method declaration. This allows later pass1 parsing
* of invocations of the method (need to know the number of
* arguments.)
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"LOADING-Method: State=%p Op=%p NamedObj=%p\n",
walk_state, op, op->named.node));
if (!acpi_ns_get_attached_object(op->named.node)) {
walk_state->operands[0] =
ACPI_CAST_PTR(void, op->named.node);
walk_state->num_operands = 1;
status =
acpi_ds_create_operands(walk_state,
op->common.value.
arg);
if (ACPI_SUCCESS(status)) {
status =
acpi_ex_create_method(op->named.
data,
op->named.
length,
walk_state);
}
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
}
/* Pop the scope stack (only if loading a table) */
if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"(%s): Popping scope for Op %p\n",
acpi_ut_get_type_name(object_type), op));
status = acpi_ds_scope_stack_pop(walk_state);
}
return_ACPI_STATUS(status);
}

View File

@@ -1,738 +0,0 @@
/******************************************************************************
*
* Module Name: dswload2 - Dispatcher second pass namespace load callbacks
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acevents.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswload2")
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_begin_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
* out_op - Wher to return op if a new one is created
*
* RETURN: Status
*
* DESCRIPTION: Descending callback used during the loading of ACPI tables.
*
******************************************************************************/
acpi_status
acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op)
{
union acpi_parse_object *op;
struct acpi_namespace_node *node;
acpi_status status;
acpi_object_type object_type;
char *buffer_ptr;
u32 flags;
ACPI_FUNCTION_TRACE(ds_load2_begin_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
walk_state));
if (op) {
if ((walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
/* We are executing a while loop outside of a method */
status = acpi_ds_exec_begin_op(walk_state, out_op);
return_ACPI_STATUS(status);
}
/* We only care about Namespace opcodes here */
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
(walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
(!(walk_state->op_info->flags & AML_NAMED))) {
return_ACPI_STATUS(AE_OK);
}
/* Get the name we are going to enter or lookup in the namespace */
if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
/* For Namepath op, get the path string */
buffer_ptr = op->common.value.string;
if (!buffer_ptr) {
/* No name, just exit */
return_ACPI_STATUS(AE_OK);
}
} else {
/* Get name from the op */
buffer_ptr = ACPI_CAST_PTR(char, &op->named.name);
}
} else {
/* Get the namestring from the raw AML */
buffer_ptr =
acpi_ps_get_next_namestring(&walk_state->parser_state);
}
/* Map the opcode into an internal object type */
object_type = walk_state->op_info->object_type;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"State=%p Op=%p Type=%X\n", walk_state, op,
object_type));
switch (walk_state->opcode) {
case AML_FIELD_OP:
case AML_BANK_FIELD_OP:
case AML_INDEX_FIELD_OP:
node = NULL;
status = AE_OK;
break;
case AML_INT_NAMEPATH_OP:
/*
* The name_path is an object reference to an existing object.
* Don't enter the name into the namespace, but look it up
* for use later.
*/
status =
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
object_type, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT, walk_state, &(node));
break;
case AML_SCOPE_OP:
/* Special case for Scope(\) -> refers to the Root node */
if (op && (op->named.node == acpi_gbl_root_node)) {
node = op->named.node;
status =
acpi_ds_scope_stack_push(node, object_type,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else {
/*
* The Path is an object reference to an existing object.
* Don't enter the name into the namespace, but look it up
* for use later.
*/
status =
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
object_type, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT, walk_state,
&(node));
if (ACPI_FAILURE(status)) {
#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
status = AE_OK;
} else {
ACPI_ERROR_NAMESPACE(buffer_ptr,
status);
}
#else
ACPI_ERROR_NAMESPACE(buffer_ptr, status);
#endif
return_ACPI_STATUS(status);
}
}
/*
* We must check to make sure that the target is
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
case ACPI_TYPE_ANY:
case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
/* These are acceptable types */
break;
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/*
* These types we will allow, but we will change the type.
* This enables some existing code of the form:
*
* Name (DEB, 0)
* Scope (DEB) { ... }
*/
ACPI_WARNING((AE_INFO,
"Type override - [%4.4s] had invalid type (%s) "
"for Scope operator, changed to type ANY",
acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
break;
case ACPI_TYPE_METHOD:
/*
* Allow scope change to root during execution of module-level
* code. Root is typed METHOD during this time.
*/
if ((node == acpi_gbl_root_node) &&
(walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
break;
}
/*lint -fallthrough */
default:
/* All other types are an error */
ACPI_ERROR((AE_INFO,
"Invalid type (%s) for target of "
"Scope operator [%4.4s] (Cannot override)",
acpi_ut_get_type_name(node->type),
acpi_ut_get_node_name(node)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
default:
/* All other opcodes */
if (op && op->common.node) {
/* This op/node was previously entered into the namespace */
node = op->common.node;
if (acpi_ns_opens_scope(object_type)) {
status =
acpi_ds_scope_stack_push(node, object_type,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
return_ACPI_STATUS(AE_OK);
}
/*
* Enter the named type into the internal namespace. We enter the name
* as we go downward in the parse tree. Any necessary subobjects that
* involve arguments to the opcode must be created as we go back up the
* parse tree later.
*
* Note: Name may already exist if we are executing a deferred opcode.
*/
if (walk_state->deferred_node) {
/* This name is already in the namespace, get the node */
node = walk_state->deferred_node;
status = AE_OK;
break;
}
flags = ACPI_NS_NO_UPSEARCH;
if (walk_state->pass_number == ACPI_IMODE_EXECUTE) {
/* Execution mode, node cannot already exist, node is temporary */
flags |= ACPI_NS_ERROR_IF_FOUND;
if (!
(walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
}
/* Add new entry or lookup existing entry */
status =
acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
object_type, ACPI_IMODE_LOAD_PASS2, flags,
walk_state, &node);
if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"***New Node [%4.4s] %p is temporary\n",
acpi_ut_get_node_name(node), node));
}
break;
}
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(buffer_ptr, status);
return_ACPI_STATUS(status);
}
if (!op) {
/* Create a new op */
op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new op */
if (node) {
op->named.name = node->name.integer;
}
*out_op = op;
}
/*
* Put the Node in the "op" object that the parser uses, so we
* can get it again quickly when this scope is closed
*/
op->common.node = node;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_end_op
*
* PARAMETERS: walk_state - Current state of the parse tree walk
*
* RETURN: Status
*
* DESCRIPTION: Ascending callback used during the loading of the namespace,
* both control methods and everything else.
*
******************************************************************************/
acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
{
union acpi_parse_object *op;
acpi_status status = AE_OK;
acpi_object_type object_type;
struct acpi_namespace_node *node;
union acpi_parse_object *arg;
struct acpi_namespace_node *new_node;
#ifndef ACPI_NO_METHOD_EXECUTION
u32 i;
u8 region_space;
#endif
ACPI_FUNCTION_TRACE(ds_load2_end_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
walk_state->op_info->name, op, walk_state));
/* Check if opcode had an associated namespace object */
if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
return_ACPI_STATUS(AE_OK);
}
if (op->common.aml_opcode == AML_SCOPE_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Ending scope Op=%p State=%p\n", op,
walk_state));
}
object_type = walk_state->op_info->object_type;
/*
* Get the Node/name from the earlier lookup
* (It was saved in the *op structure)
*/
node = op->common.node;
/*
* Put the Node on the object stack (Contains the ACPI Name of
* this object)
*/
walk_state->operands[0] = (void *)node;
walk_state->num_operands = 1;
/* Pop the scope stack */
if (acpi_ns_opens_scope(object_type) &&
(op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"(%s) Popping scope for Op %p\n",
acpi_ut_get_type_name(object_type), op));
status = acpi_ds_scope_stack_pop(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
/*
* Named operations are as follows:
*
* AML_ALIAS
* AML_BANKFIELD
* AML_CREATEBITFIELD
* AML_CREATEBYTEFIELD
* AML_CREATEDWORDFIELD
* AML_CREATEFIELD
* AML_CREATEQWORDFIELD
* AML_CREATEWORDFIELD
* AML_DATA_REGION
* AML_DEVICE
* AML_EVENT
* AML_FIELD
* AML_INDEXFIELD
* AML_METHOD
* AML_METHODCALL
* AML_MUTEX
* AML_NAME
* AML_NAMEDFIELD
* AML_OPREGION
* AML_POWERRES
* AML_PROCESSOR
* AML_SCOPE
* AML_THERMALZONE
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
acpi_ps_get_opcode_name(op->common.aml_opcode),
walk_state, op, node));
/* Decode the opcode */
arg = op->common.value.arg;
switch (walk_state->op_info->type) {
#ifndef ACPI_NO_METHOD_EXECUTION
case AML_TYPE_CREATE_FIELD:
/*
* Create the field object, but the field buffer and index must
* be evaluated later during the execution phase
*/
status = acpi_ds_create_buffer_field(op, walk_state);
break;
case AML_TYPE_NAMED_FIELD:
/*
* If we are executing a method, initialize the field
*/
if (walk_state->method_node) {
status = acpi_ds_init_field_objects(op, walk_state);
}
switch (op->common.aml_opcode) {
case AML_INDEX_FIELD_OP:
status =
acpi_ds_create_index_field(op,
(acpi_handle) arg->
common.node, walk_state);
break;
case AML_BANK_FIELD_OP:
status =
acpi_ds_create_bank_field(op, arg->common.node,
walk_state);
break;
case AML_FIELD_OP:
status =
acpi_ds_create_field(op, arg->common.node,
walk_state);
break;
default:
/* All NAMED_FIELD opcodes must be handled above */
break;
}
break;
case AML_TYPE_NAMED_SIMPLE:
status = acpi_ds_create_operands(walk_state, arg);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
switch (op->common.aml_opcode) {
case AML_PROCESSOR_OP:
status = acpi_ex_create_processor(walk_state);
break;
case AML_POWER_RES_OP:
status = acpi_ex_create_power_resource(walk_state);
break;
case AML_MUTEX_OP:
status = acpi_ex_create_mutex(walk_state);
break;
case AML_EVENT_OP:
status = acpi_ex_create_event(walk_state);
break;
case AML_ALIAS_OP:
status = acpi_ex_create_alias(walk_state);
break;
default:
/* Unknown opcode */
status = AE_OK;
goto cleanup;
}
/* Delete operands */
for (i = 1; i < walk_state->num_operands; i++) {
acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
break;
#endif /* ACPI_NO_METHOD_EXECUTION */
case AML_TYPE_NAMED_COMPLEX:
switch (op->common.aml_opcode) {
#ifndef ACPI_NO_METHOD_EXECUTION
case AML_REGION_OP:
case AML_DATA_REGION_OP:
if (op->common.aml_opcode == AML_REGION_OP) {
region_space = (acpi_adr_space_type)
((op->common.value.arg)->common.value.
integer);
} else {
region_space = ACPI_ADR_SPACE_DATA_TABLE;
}
/*
* The op_region is not fully parsed at this time. The only valid
* argument is the space_id. (We must save the address of the
* AML of the address and length operands)
*
* If we have a valid region, initialize it. The namespace is
* unlocked at this point.
*
* Need to unlock interpreter if it is locked (if we are running
* a control method), in order to allow _REG methods to be run
* during acpi_ev_initialize_region.
*/
if (walk_state->method_node) {
/*
* Executing a method: initialize the region and unlock
* the interpreter
*/
status =
acpi_ex_create_region(op->named.data,
op->named.length,
region_space,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ex_exit_interpreter();
}
status =
acpi_ev_initialize_region
(acpi_ns_get_attached_object(node), FALSE);
if (walk_state->method_node) {
acpi_ex_enter_interpreter();
}
if (ACPI_FAILURE(status)) {
/*
* If AE_NOT_EXIST is returned, it is not fatal
* because many regions get created before a handler
* is installed for said region.
*/
if (AE_NOT_EXIST == status) {
status = AE_OK;
}
}
break;
case AML_NAME_OP:
status = acpi_ds_create_node(walk_state, node, op);
break;
case AML_METHOD_OP:
/*
* method_op pkg_length name_string method_flags term_list
*
* Note: We must create the method node/object pair as soon as we
* see the method declaration. This allows later pass1 parsing
* of invocations of the method (need to know the number of
* arguments.)
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"LOADING-Method: State=%p Op=%p NamedObj=%p\n",
walk_state, op, op->named.node));
if (!acpi_ns_get_attached_object(op->named.node)) {
walk_state->operands[0] =
ACPI_CAST_PTR(void, op->named.node);
walk_state->num_operands = 1;
status =
acpi_ds_create_operands(walk_state,
op->common.value.
arg);
if (ACPI_SUCCESS(status)) {
status =
acpi_ex_create_method(op->named.
data,
op->named.
length,
walk_state);
}
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
break;
#endif /* ACPI_NO_METHOD_EXECUTION */
default:
/* All NAMED_COMPLEX opcodes must be handled above */
break;
}
break;
case AML_CLASS_INTERNAL:
/* case AML_INT_NAMEPATH_OP: */
break;
case AML_CLASS_METHOD_CALL:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
walk_state, op, node));
/*
* Lookup the method name and save the Node
*/
status =
acpi_ns_lookup(walk_state->scope_info,
arg->common.value.string, ACPI_TYPE_ANY,
ACPI_IMODE_LOAD_PASS2,
ACPI_NS_SEARCH_PARENT |
ACPI_NS_DONT_OPEN_SCOPE, walk_state,
&(new_node));
if (ACPI_SUCCESS(status)) {
/*
* Make sure that what we found is indeed a method
* We didn't search for a method on purpose, to see if the name
* would resolve
*/
if (new_node->type != ACPI_TYPE_METHOD) {
status = AE_AML_OPERAND_TYPE;
}
/* We could put the returned object (Node) on the object stack for
* later, but for now, we will put it in the "op" object that the
* parser uses, so we can get it again at the end of this scope
*/
op->common.node = new_node;
} else {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
}
break;
default:
break;
}
cleanup:
/* Remove the Node pushed at the very beginning */
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
return_ACPI_STATUS(status);
}

View File

@@ -1,214 +0,0 @@
/******************************************************************************
*
* Module Name: dswscope - Scope stack manipulation
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswscope")
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_clear
*
* PARAMETERS: walk_state - Current state
*
* RETURN: None
*
* DESCRIPTION: Pop (and free) everything on the scope stack except the
* root scope object (which remains at the stack top.)
*
***************************************************************************/
void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *scope_info;
ACPI_FUNCTION_NAME(ds_scope_stack_clear);
while (walk_state->scope_info) {
/* Pop a scope off the stack */
scope_info = walk_state->scope_info;
walk_state->scope_info = scope_info->scope.next;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Popped object type (%s)\n",
acpi_ut_get_type_name(scope_info->common.
value)));
acpi_ut_delete_generic_state(scope_info);
}
}
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_push
*
* PARAMETERS: node - Name to be made current
* type - Type of frame being pushed
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Push the current scope on the scope stack, and make the
* passed Node current.
*
***************************************************************************/
acpi_status
acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
acpi_object_type type,
struct acpi_walk_state *walk_state)
{
union acpi_generic_state *scope_info;
union acpi_generic_state *old_scope_info;
ACPI_FUNCTION_TRACE(ds_scope_stack_push);
if (!node) {
/* Invalid scope */
ACPI_ERROR((AE_INFO, "Null scope parameter"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Make sure object type is valid */
if (!acpi_ut_valid_object_type(type)) {
ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type));
}
/* Allocate a new scope object */
scope_info = acpi_ut_create_generic_state();
if (!scope_info) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init new scope object */
scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE;
scope_info->scope.node = node;
scope_info->common.value = (u16) type;
walk_state->scope_depth++;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[%.2d] Pushed scope ",
(u32) walk_state->scope_depth));
old_scope_info = walk_state->scope_info;
if (old_scope_info) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
"[%4.4s] (%s)",
acpi_ut_get_node_name(old_scope_info->
scope.node),
acpi_ut_get_type_name(old_scope_info->
common.value)));
} else {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
", New scope -> [%4.4s] (%s)\n",
acpi_ut_get_node_name(scope_info->scope.node),
acpi_ut_get_type_name(scope_info->common.value)));
/* Push new scope object onto stack */
acpi_ut_push_generic_state(&walk_state->scope_info, scope_info);
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_pop
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Pop the scope stack once.
*
***************************************************************************/
acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *scope_info;
union acpi_generic_state *new_scope_info;
ACPI_FUNCTION_TRACE(ds_scope_stack_pop);
/*
* Pop scope info object off the stack.
*/
scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info);
if (!scope_info) {
return_ACPI_STATUS(AE_STACK_UNDERFLOW);
}
walk_state->scope_depth--;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
(u32) walk_state->scope_depth,
acpi_ut_get_node_name(scope_info->scope.node),
acpi_ut_get_type_name(scope_info->common.value)));
new_scope_info = walk_state->scope_info;
if (new_scope_info) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
"[%4.4s] (%s)\n",
acpi_ut_get_node_name(new_scope_info->
scope.node),
acpi_ut_get_type_name(new_scope_info->
common.value)));
} else {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n"));
}
acpi_ut_delete_generic_state(scope_info);
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,757 +0,0 @@
/******************************************************************************
*
* Module Name: dswstate - Dispatcher parse tree walk management routines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "acdispat.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswstate")
/* Local prototypes */
static acpi_status
acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_pop
*
* PARAMETERS: object - Where to return the popped object
* walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Pop an object off the top of this walk's result stack
*
******************************************************************************/
acpi_status
acpi_ds_result_pop(union acpi_operand_object **object,
struct acpi_walk_state *walk_state)
{
u32 index;
union acpi_generic_state *state;
acpi_status status;
ACPI_FUNCTION_NAME(ds_result_pop);
state = walk_state->results;
/* Incorrect state of result stack */
if (state && !walk_state->result_count) {
ACPI_ERROR((AE_INFO, "No results on result stack"));
return (AE_AML_INTERNAL);
}
if (!state && walk_state->result_count) {
ACPI_ERROR((AE_INFO, "No result state for result stack"));
return (AE_AML_INTERNAL);
}
/* Empty result stack */
if (!state) {
ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
/* Return object of the top element and clean that top element result stack */
walk_state->result_count--;
index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
*object = state->results.obj_desc[index];
if (!*object) {
ACPI_ERROR((AE_INFO,
"No result objects on result stack, State=%p",
walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
state->results.obj_desc[index] = NULL;
if (index == 0) {
status = acpi_ds_result_stack_pop(walk_state);
if (ACPI_FAILURE(status)) {
return (status);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Obj=%p [%s] Index=%X State=%p Num=%X\n", *object,
acpi_ut_get_object_type_name(*object),
index, walk_state, walk_state->result_count));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_push
*
* PARAMETERS: object - Where to return the popped object
* walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Push an object onto the current result stack
*
******************************************************************************/
acpi_status
acpi_ds_result_push(union acpi_operand_object * object,
struct acpi_walk_state * walk_state)
{
union acpi_generic_state *state;
acpi_status status;
u32 index;
ACPI_FUNCTION_NAME(ds_result_push);
if (walk_state->result_count > walk_state->result_size) {
ACPI_ERROR((AE_INFO, "Result stack is full"));
return (AE_AML_INTERNAL);
} else if (walk_state->result_count == walk_state->result_size) {
/* Extend the result stack */
status = acpi_ds_result_stack_push(walk_state);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Failed to extend the result stack"));
return (status);
}
}
if (!(walk_state->result_count < walk_state->result_size)) {
ACPI_ERROR((AE_INFO, "No free elements in result stack"));
return (AE_AML_INTERNAL);
}
state = walk_state->results;
if (!state) {
ACPI_ERROR((AE_INFO, "No result stack frame during push"));
return (AE_AML_INTERNAL);
}
if (!object) {
ACPI_ERROR((AE_INFO,
"Null Object! Obj=%p State=%p Num=%u",
object, walk_state, walk_state->result_count));
return (AE_BAD_PARAMETER);
}
/* Assign the address of object to the top free element of result stack */
index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
state->results.obj_desc[index] = object;
walk_state->result_count++;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
object,
acpi_ut_get_object_type_name((union
acpi_operand_object *)
object), walk_state,
walk_state->result_count,
walk_state->current_result));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_push
*
* PARAMETERS: walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Push an object onto the walk_state result stack
*
******************************************************************************/
static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *state;
ACPI_FUNCTION_NAME(ds_result_stack_push);
/* Check for stack overflow */
if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) >
ACPI_RESULTS_OBJ_NUM_MAX) {
ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%u",
walk_state, walk_state->result_size));
return (AE_STACK_OVERFLOW);
}
state = acpi_ut_create_generic_state();
if (!state) {
return (AE_NO_MEMORY);
}
state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT;
acpi_ut_push_generic_state(&walk_state->results, state);
/* Increase the length of the result stack by the length of frame */
walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
state, walk_state));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_pop
*
* PARAMETERS: walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Pop an object off of the walk_state result stack
*
******************************************************************************/
static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *state;
ACPI_FUNCTION_NAME(ds_result_stack_pop);
/* Check for stack underflow */
if (walk_state->results == NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Result stack underflow - State=%p\n",
walk_state));
return (AE_AML_NO_OPERAND);
}
if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) {
ACPI_ERROR((AE_INFO, "Insufficient result stack size"));
return (AE_AML_INTERNAL);
}
state = acpi_ut_pop_generic_state(&walk_state->results);
acpi_ut_delete_generic_state(state);
/* Decrease the length of result stack by the length of frame */
walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Result=%p RemainingResults=%X State=%p\n",
state, walk_state->result_count, walk_state));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_push
*
* PARAMETERS: object - Object to push
* walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Push an object onto this walk's object/operand stack
*
******************************************************************************/
acpi_status
acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
{
ACPI_FUNCTION_NAME(ds_obj_stack_push);
/* Check for stack overflow */
if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
ACPI_ERROR((AE_INFO,
"Object stack overflow! Obj=%p State=%p #Ops=%u",
object, walk_state, walk_state->num_operands));
return (AE_STACK_OVERFLOW);
}
/* Put the object onto the stack */
walk_state->operands[walk_state->operand_index] = object;
walk_state->num_operands++;
/* For the usual order of filling the operand stack */
walk_state->operand_index++;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
object,
acpi_ut_get_object_type_name((union
acpi_operand_object *)
object), walk_state,
walk_state->num_operands));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop
*
* PARAMETERS: pop_count - Number of objects/entries to pop
* walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
* deleted by this routine.
*
******************************************************************************/
acpi_status
acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
{
u32 i;
ACPI_FUNCTION_NAME(ds_obj_stack_pop);
for (i = 0; i < pop_count; i++) {
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
ACPI_ERROR((AE_INFO,
"Object stack underflow! Count=%X State=%p #Ops=%u",
pop_count, walk_state,
walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
/* Just set the stack entry to null */
walk_state->num_operands--;
walk_state->operands[walk_state->num_operands] = NULL;
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n",
pop_count, walk_state, walk_state->num_operands));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop_and_delete
*
* PARAMETERS: pop_count - Number of objects/entries to pop
* walk_state - Current Walk state
*
* RETURN: Status
*
* DESCRIPTION: Pop this walk's object stack and delete each object that is
* popped off.
*
******************************************************************************/
void
acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
struct acpi_walk_state *walk_state)
{
s32 i;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
if (pop_count == 0) {
return;
}
for (i = (s32) pop_count - 1; i >= 0; i--) {
if (walk_state->num_operands == 0) {
return;
}
/* Pop the stack and delete an object if present in this stack entry */
walk_state->num_operands--;
obj_desc = walk_state->operands[i];
if (obj_desc) {
acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
pop_count, walk_state, walk_state->num_operands));
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_current_walk_state
*
* PARAMETERS: thread - Get current active state for this Thread
*
* RETURN: Pointer to the current walk state
*
* DESCRIPTION: Get the walk state that is at the head of the list (the "current"
* walk state.)
*
******************************************************************************/
struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
*thread)
{
ACPI_FUNCTION_NAME(ds_get_current_walk_state);
if (!thread) {
return (NULL);
}
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n",
thread->walk_state_list));
return (thread->walk_state_list);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_push_walk_state
*
* PARAMETERS: walk_state - State to push
* thread - Thread state object
*
* RETURN: None
*
* DESCRIPTION: Place the Thread state at the head of the state list
*
******************************************************************************/
void
acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
struct acpi_thread_state *thread)
{
ACPI_FUNCTION_TRACE(ds_push_walk_state);
walk_state->next = thread->walk_state_list;
thread->walk_state_list = walk_state;
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_pop_walk_state
*
* PARAMETERS: thread - Current thread state
*
* RETURN: A walk_state object popped from the thread's stack
*
* DESCRIPTION: Remove and return the walkstate object that is at the head of
* the walk stack for the given walk list. NULL indicates that
* the list is empty.
*
******************************************************************************/
struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
{
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_TRACE(ds_pop_walk_state);
walk_state = thread->walk_state_list;
if (walk_state) {
/* Next walk state becomes the current walk state */
thread->walk_state_list = walk_state->next;
/*
* Don't clear the NEXT field, this serves as an indicator
* that there is a parent WALK STATE
* Do Not: walk_state->Next = NULL;
*/
}
return_PTR(walk_state);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_walk_state
*
* PARAMETERS: owner_id - ID for object creation
* origin - Starting point for this walk
* method_desc - Method object
* thread - Current thread state
*
* RETURN: Pointer to the new walk state.
*
* DESCRIPTION: Allocate and initialize a new walk state. The current walk
* state is set to this new state.
*
******************************************************************************/
struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
union acpi_parse_object
*origin,
union acpi_operand_object
*method_desc,
struct acpi_thread_state
*thread)
{
struct acpi_walk_state *walk_state;
ACPI_FUNCTION_TRACE(ds_create_walk_state);
walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state));
if (!walk_state) {
return_PTR(NULL);
}
walk_state->descriptor_type = ACPI_DESC_TYPE_WALK;
walk_state->method_desc = method_desc;
walk_state->owner_id = owner_id;
walk_state->origin = origin;
walk_state->thread = thread;
walk_state->parser_state.start_op = origin;
/* Init the method args/local */
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
acpi_ds_method_data_init(walk_state);
#endif
/* Put the new state at the head of the walk list */
if (thread) {
acpi_ds_push_walk_state(walk_state, thread);
}
return_PTR(walk_state);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_aml_walk
*
* PARAMETERS: walk_state - New state to be initialized
* op - Current parse op
* method_node - Control method NS node, if any
* aml_start - Start of AML
* aml_length - Length of AML
* info - Method info block (params, etc.)
* pass_number - 1, 2, or 3
*
* RETURN: Status
*
* DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
*
******************************************************************************/
acpi_status
acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
union acpi_parse_object *op,
struct acpi_namespace_node *method_node,
u8 * aml_start,
u32 aml_length,
struct acpi_evaluate_info *info, u8 pass_number)
{
acpi_status status;
struct acpi_parse_state *parser_state = &walk_state->parser_state;
union acpi_parse_object *extra_op;
ACPI_FUNCTION_TRACE(ds_init_aml_walk);
walk_state->parser_state.aml =
walk_state->parser_state.aml_start = aml_start;
walk_state->parser_state.aml_end =
walk_state->parser_state.pkg_end = aml_start + aml_length;
/* The next_op of the next_walk will be the beginning of the method */
walk_state->next_op = NULL;
walk_state->pass_number = pass_number;
if (info) {
walk_state->params = info->parameters;
walk_state->caller_return_desc = &info->return_object;
}
status = acpi_ps_init_scope(&walk_state->parser_state, op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (method_node) {
walk_state->parser_state.start_node = method_node;
walk_state->walk_type = ACPI_WALK_METHOD;
walk_state->method_node = method_node;
walk_state->method_desc =
acpi_ns_get_attached_object(method_node);
/* Push start scope on scope stack and make it current */
status =
acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Init the method arguments */
status = acpi_ds_method_data_init_args(walk_state->params,
ACPI_METHOD_NUM_ARGS,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else {
/*
* Setup the current scope.
* Find a Named Op that has a namespace node associated with it.
* search upwards from this Op. Current scope is the first
* Op with a namespace node.
*/
extra_op = parser_state->start_op;
while (extra_op && !extra_op->common.node) {
extra_op = extra_op->common.parent;
}
if (!extra_op) {
parser_state->start_node = NULL;
} else {
parser_state->start_node = extra_op->common.node;
}
if (parser_state->start_node) {
/* Push start scope on scope stack and make it current */
status =
acpi_ds_scope_stack_push(parser_state->start_node,
parser_state->start_node->
type, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
status = acpi_ds_init_callbacks(walk_state, pass_number);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_walk_state
*
* PARAMETERS: walk_state - State to delete
*
* RETURN: Status
*
* DESCRIPTION: Delete a walk state including all internal data structures
*
******************************************************************************/
void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *state;
ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
if (!walk_state) {
return_VOID;
}
if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
walk_state));
return_VOID;
}
/* There should not be any open scopes */
if (walk_state->parser_state.scope) {
ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
walk_state));
acpi_ps_cleanup_scope(&walk_state->parser_state);
}
/* Always must free any linked control states */
while (walk_state->control_state) {
state = walk_state->control_state;
walk_state->control_state = state->common.next;
acpi_ut_delete_generic_state(state);
}
/* Always must free any linked parse states */
while (walk_state->scope_info) {
state = walk_state->scope_info;
walk_state->scope_info = state->common.next;
acpi_ut_delete_generic_state(state);
}
/* Always must free any stacked result states */
while (walk_state->results) {
state = walk_state->results;
walk_state->results = state->common.next;
acpi_ut_delete_generic_state(state);
}
ACPI_FREE(walk_state);
return_VOID;
}

View File

@@ -1,297 +0,0 @@
/******************************************************************************
*
* Module Name: evevent - Fixed Event handling and dispatch
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evevent")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status acpi_ev_fixed_event_initialize(void);
static u32 acpi_ev_fixed_event_dispatch(u32 event);
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_events
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
*
******************************************************************************/
acpi_status acpi_ev_initialize_events(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_initialize_events);
/* If Hardware Reduced flag is set, there are no fixed events */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
/*
* Initialize the Fixed and General Purpose Events. This is done prior to
* enabling SCIs to prevent interrupts from occurring before the handlers
* are installed.
*/
status = acpi_ev_fixed_event_initialize();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to initialize fixed events"));
return_ACPI_STATUS(status);
}
status = acpi_ev_gpe_initialize();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to initialize general purpose events"));
return_ACPI_STATUS(status);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_xrupt_handlers
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
*
******************************************************************************/
acpi_status acpi_ev_install_xrupt_handlers(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
/* If Hardware Reduced flag is set, there is no ACPI h/w */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
/* Install the SCI handler */
status = acpi_ev_install_sci_handler();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to install System Control Interrupt handler"));
return_ACPI_STATUS(status);
}
/* Install the handler for the Global Lock */
status = acpi_ev_init_global_lock_handler();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to initialize Global Lock handler"));
return_ACPI_STATUS(status);
}
acpi_gbl_events_initialized = TRUE;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_initialize
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Install the fixed event handlers and disable all fixed events.
*
******************************************************************************/
static acpi_status acpi_ev_fixed_event_initialize(void)
{
u32 i;
acpi_status status;
/*
* Initialize the structure that keeps track of fixed event handlers and
* enable the fixed events.
*/
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
acpi_gbl_fixed_event_handlers[i].handler = NULL;
acpi_gbl_fixed_event_handlers[i].context = NULL;
/* Disable the fixed event */
if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
status =
acpi_write_bit_register(acpi_gbl_fixed_event_info
[i].enable_register_id,
ACPI_DISABLE_EVENT);
if (ACPI_FAILURE(status)) {
return (status);
}
}
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_detect
*
* PARAMETERS: None
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
* DESCRIPTION: Checks the PM status register for active fixed events
*
******************************************************************************/
u32 acpi_ev_fixed_event_detect(void)
{
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u32 fixed_status;
u32 fixed_enable;
u32 i;
ACPI_FUNCTION_NAME(ev_fixed_event_detect);
/*
* Read the fixed feature status and enable registers, as all the cases
* depend on their values. Ignore errors here.
*/
(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Fixed Event Block: Enable %08X Status %08X\n",
fixed_enable, fixed_status));
/*
* Check for all possible Fixed Events and dispatch those that are active
*/
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
/* Both the status and enable bits must be on for this event */
if ((fixed_status & acpi_gbl_fixed_event_info[i].
status_bit_mask)
&& (fixed_enable & acpi_gbl_fixed_event_info[i].
enable_bit_mask)) {
/*
* Found an active (signalled) event. Invoke global event
* handler if present.
*/
acpi_fixed_event_count[i]++;
if (acpi_gbl_global_event_handler) {
acpi_gbl_global_event_handler
(ACPI_EVENT_TYPE_FIXED, NULL, i,
acpi_gbl_global_event_handler_context);
}
int_status |= acpi_ev_fixed_event_dispatch(i);
}
}
return (int_status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_dispatch
*
* PARAMETERS: event - Event type
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
* DESCRIPTION: Clears the status bit for the requested event, calls the
* handler that previously registered for the event.
* NOTE: If there is no handler for the event, the event is
* disabled to prevent further interrupts.
*
******************************************************************************/
static u32 acpi_ev_fixed_event_dispatch(u32 event)
{
ACPI_FUNCTION_ENTRY();
/* Clear the status bit */
(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
status_register_id, ACPI_CLEAR_STATUS);
/*
* Make sure that a handler exists. If not, report an error
* and disable the event to prevent further interrupts.
*/
if (!acpi_gbl_fixed_event_handlers[event].handler) {
(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id,
ACPI_DISABLE_EVENT);
ACPI_ERROR((AE_INFO,
"No installed handler for fixed event - %s (%u), disabling",
acpi_ut_get_event_name(event), event));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
/* Invoke the Fixed Event handler */
return ((acpi_gbl_fixed_event_handlers[event].
handler) (acpi_gbl_fixed_event_handlers[event].context));
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,344 +0,0 @@
/******************************************************************************
*
* Module Name: evglock - Global Lock support
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evglock")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static u32 acpi_ev_global_lock_handler(void *context);
/*******************************************************************************
*
* FUNCTION: acpi_ev_init_global_lock_handler
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Install a handler for the global lock release event
*
******************************************************************************/
acpi_status acpi_ev_init_global_lock_handler(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
/* If Hardware Reduced flag is set, there is no global lock */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
/* Attempt installation of the global lock handler */
status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
acpi_ev_global_lock_handler,
NULL);
/*
* If the global lock does not exist on this platform, the attempt to
* enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick).
* Map to AE_OK, but mark global lock as not present. Any attempt to
* actually use the global lock will be flagged with an error.
*/
acpi_gbl_global_lock_present = FALSE;
if (status == AE_NO_HARDWARE_RESPONSE) {
ACPI_ERROR((AE_INFO,
"No response from Global Lock hardware, disabling lock"));
return_ACPI_STATUS(AE_OK);
}
status = acpi_os_create_lock(&acpi_gbl_global_lock_pending_lock);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_global_lock_pending = FALSE;
acpi_gbl_global_lock_present = TRUE;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_remove_global_lock_handler
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Remove the handler for the Global Lock
*
******************************************************************************/
acpi_status acpi_ev_remove_global_lock_handler(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler);
acpi_gbl_global_lock_present = FALSE;
status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL,
acpi_ev_global_lock_handler);
acpi_os_delete_lock(acpi_gbl_global_lock_pending_lock);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_global_lock_handler
*
* PARAMETERS: context - From thread interface, not used
*
* RETURN: ACPI_INTERRUPT_HANDLED
*
* DESCRIPTION: Invoked directly from the SCI handler when a global lock
* release interrupt occurs. If there is actually a pending
* request for the lock, signal the waiting thread.
*
******************************************************************************/
static u32 acpi_ev_global_lock_handler(void *context)
{
acpi_status status;
acpi_cpu_flags flags;
flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock);
/*
* If a request for the global lock is not actually pending,
* we are done. This handles "spurious" global lock interrupts
* which are possible (and have been seen) with bad BIOSs.
*/
if (!acpi_gbl_global_lock_pending) {
goto cleanup_and_exit;
}
/*
* Send a unit to the global lock semaphore. The actual acquisition
* of the global lock will be performed by the waiting thread.
*/
status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));
}
acpi_gbl_global_lock_pending = FALSE;
cleanup_and_exit:
acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags);
return (ACPI_INTERRUPT_HANDLED);
}
/******************************************************************************
*
* FUNCTION: acpi_ev_acquire_global_lock
*
* PARAMETERS: timeout - Max time to wait for the lock, in millisec.
*
* RETURN: Status
*
* DESCRIPTION: Attempt to gain ownership of the Global Lock.
*
* MUTEX: Interpreter must be locked
*
* Note: The original implementation allowed multiple threads to "acquire" the
* Global Lock, and the OS would hold the lock until the last thread had
* released it. However, this could potentially starve the BIOS out of the
* lock, especially in the case where there is a tight handshake between the
* Embedded Controller driver and the BIOS. Therefore, this implementation
* allows only one thread to acquire the HW Global Lock at a time, and makes
* the global lock appear as a standard mutex on the OS side.
*
*****************************************************************************/
acpi_status acpi_ev_acquire_global_lock(u16 timeout)
{
acpi_cpu_flags flags;
acpi_status status;
u8 acquired = FALSE;
ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
/*
* Only one thread can acquire the GL at a time, the global_lock_mutex
* enforces this. This interface releases the interpreter if we must wait.
*/
status =
acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex->mutex.
os_mutex, timeout);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Update the global lock handle and check for wraparound. The handle is
* only used for the external global lock interfaces, but it is updated
* here to properly handle the case where a single thread may acquire the
* lock via both the AML and the acpi_acquire_global_lock interfaces. The
* handle is therefore updated on the first acquire from a given thread
* regardless of where the acquisition request originated.
*/
acpi_gbl_global_lock_handle++;
if (acpi_gbl_global_lock_handle == 0) {
acpi_gbl_global_lock_handle = 1;
}
/*
* Make sure that a global lock actually exists. If not, just
* treat the lock as a standard mutex.
*/
if (!acpi_gbl_global_lock_present) {
acpi_gbl_global_lock_acquired = TRUE;
return_ACPI_STATUS(AE_OK);
}
flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock);
do {
/* Attempt to acquire the actual hardware lock */
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
if (acquired) {
acpi_gbl_global_lock_acquired = TRUE;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Acquired hardware Global Lock\n"));
break;
}
/*
* Did not get the lock. The pending bit was set above, and
* we must now wait until we receive the global lock
* released interrupt.
*/
acpi_gbl_global_lock_pending = TRUE;
acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Waiting for hardware Global Lock\n"));
/*
* Wait for handshake with the global lock interrupt handler.
* This interface releases the interpreter if we must wait.
*/
status =
acpi_ex_system_wait_semaphore
(acpi_gbl_global_lock_semaphore, ACPI_WAIT_FOREVER);
flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock);
} while (ACPI_SUCCESS(status));
acpi_gbl_global_lock_pending = FALSE;
acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_release_global_lock
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Releases ownership of the Global Lock.
*
******************************************************************************/
acpi_status acpi_ev_release_global_lock(void)
{
u8 pending = FALSE;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ev_release_global_lock);
/* Lock must be already acquired */
if (!acpi_gbl_global_lock_acquired) {
ACPI_WARNING((AE_INFO,
"Cannot release the ACPI Global Lock, it has not been acquired"));
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
if (acpi_gbl_global_lock_present) {
/* Allow any thread to release the lock */
ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending);
/*
* If the pending bit was set, we must write GBL_RLS to the control
* register
*/
if (pending) {
status =
acpi_write_bit_register
(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
ACPI_ENABLE_EVENT);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Released hardware Global Lock\n"));
}
acpi_gbl_global_lock_acquired = FALSE;
/* Release the local GL mutex */
acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,798 +0,0 @@
/******************************************************************************
*
* Module Name: evgpe - General Purpose Event handling and dispatch
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context);
/*******************************************************************************
*
* FUNCTION: acpi_ev_update_gpe_enable_mask
*
* PARAMETERS: gpe_event_info - GPE to update
*
* RETURN: Status
*
* DESCRIPTION: Updates GPE register enable mask based upon whether there are
* runtime references to this GPE
*
******************************************************************************/
acpi_status
acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
u32 register_bit;
ACPI_FUNCTION_TRACE(ev_update_gpe_enable_mask);
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* Clear the run bit up front */
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
/* Set the mask bit only if there are references to this GPE */
if (gpe_event_info->runtime_count) {
ACPI_SET_BIT(gpe_register_info->enable_for_run,
(u8)register_bit);
}
gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_enable_gpe
*
* PARAMETERS: gpe_event_info - GPE to enable
*
* RETURN: Status
*
* DESCRIPTION: Clear a GPE of stale events and enable it.
*
******************************************************************************/
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_enable_gpe);
/* Clear the GPE (of stale events) */
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Enable the requested GPE */
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_add_gpe_reference
*
* PARAMETERS: gpe_event_info - Add a reference to this GPE
*
* RETURN: Status
*
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
* hardware-enabled.
*
******************************************************************************/
acpi_status
acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ev_add_gpe_reference);
if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
return_ACPI_STATUS(AE_LIMIT);
}
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
/* Enable on first reference */
status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
if (ACPI_SUCCESS(status)) {
status = acpi_ev_enable_gpe(gpe_event_info);
}
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--;
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_remove_gpe_reference
*
* PARAMETERS: gpe_event_info - Remove a reference to this GPE
*
* RETURN: Status
*
* DESCRIPTION: Remove a reference to a GPE. When the last reference is
* removed, the GPE is hardware-disabled.
*
******************************************************************************/
acpi_status
acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ev_remove_gpe_reference);
if (!gpe_event_info->runtime_count) {
return_ACPI_STATUS(AE_LIMIT);
}
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
/* Disable on last reference */
status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
if (ACPI_SUCCESS(status)) {
status =
acpi_hw_low_set_gpe(gpe_event_info,
ACPI_GPE_DISABLE);
}
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_low_get_gpe_info
*
* PARAMETERS: gpe_number - Raw GPE number
* gpe_block - A GPE info block
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE (The gpe_number
* is not within the specified GPE block)
*
* DESCRIPTION: Returns the event_info struct associated with this GPE. This is
* the low-level implementation of ev_get_gpe_event_info.
*
******************************************************************************/
struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block)
{
u32 gpe_index;
/*
* Validate that the gpe_number is within the specified gpe_block.
* (Two steps)
*/
if (!gpe_block || (gpe_number < gpe_block->block_base_number)) {
return (NULL);
}
gpe_index = gpe_number - gpe_block->block_base_number;
if (gpe_index >= gpe_block->gpe_count) {
return (NULL);
}
return (&gpe_block->event_info[gpe_index]);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_event_info
*
* PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
* gpe_number - Raw GPE number
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE
*
* DESCRIPTION: Returns the event_info struct associated with this GPE.
* Validates the gpe_block and the gpe_number
*
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
******************************************************************************/
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number)
{
union acpi_operand_object *obj_desc;
struct acpi_gpe_event_info *gpe_info;
u32 i;
ACPI_FUNCTION_ENTRY();
/* A NULL gpe_device means use the FADT-defined GPE block(s) */
if (!gpe_device) {
/* Examine GPE Block 0 and 1 (These blocks are permanent) */
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
gpe_info = acpi_ev_low_get_gpe_info(gpe_number,
acpi_gbl_gpe_fadt_blocks
[i]);
if (gpe_info) {
return (gpe_info);
}
}
/* The gpe_number was not in the range of either FADT GPE block */
return (NULL);
}
/* A Non-NULL gpe_device means this is a GPE Block Device */
obj_desc =
acpi_ns_get_attached_object((struct acpi_namespace_node *)
gpe_device);
if (!obj_desc || !obj_desc->device.gpe_block) {
return (NULL);
}
return (acpi_ev_low_get_gpe_info
(gpe_number, obj_desc->device.gpe_block));
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_detect
*
* PARAMETERS: gpe_xrupt_list - Interrupt block for this interrupt.
* Can have multiple GPE blocks attached.
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
* DESCRIPTION: Detect if any GP events have occurred. This function is
* executed at interrupt level.
*
******************************************************************************/
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list)
{
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
struct acpi_namespace_node *gpe_device;
struct acpi_gpe_register_info *gpe_register_info;
struct acpi_gpe_event_info *gpe_event_info;
u32 gpe_number;
struct acpi_gpe_handler_info *gpe_handler_info;
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u8 enabled_status_byte;
u32 status_reg;
u32 enable_reg;
acpi_cpu_flags flags;
u32 i;
u32 j;
ACPI_FUNCTION_NAME(ev_gpe_detect);
/* Check for the case where there are no GPEs */
if (!gpe_xrupt_list) {
return (int_status);
}
/*
* We need to obtain the GPE lock for both the data structs and registers
* Note: Not necessary to obtain the hardware lock, since the GPE
* registers are owned by the gpe_lock.
*/
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Examine all GPE blocks attached to this interrupt level */
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) {
gpe_device = gpe_block->node;
/*
* Read all of the 8-bit GPE status and enable registers in this GPE
* block, saving all of them. Find all currently active GP events.
*/
for (i = 0; i < gpe_block->register_count; i++) {
/* Get the next status/enable pair */
gpe_register_info = &gpe_block->register_info[i];
/*
* Optimization: If there are no GPEs enabled within this
* register, we can safely ignore the entire register.
*/
if (!(gpe_register_info->enable_for_run |
gpe_register_info->enable_for_wake)) {
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Ignore disabled registers for GPE %02X-%02X: "
"RunEnable=%02X, WakeEnable=%02X\n",
gpe_register_info->
base_gpe_number,
gpe_register_info->
base_gpe_number +
(ACPI_GPE_REGISTER_WIDTH - 1),
gpe_register_info->
enable_for_run,
gpe_register_info->
enable_for_wake));
continue;
}
/* Read the Status Register */
status =
acpi_hw_read(&status_reg,
&gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Read the Enable Register */
status =
acpi_hw_read(&enable_reg,
&gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
"RunEnable=%02X, WakeEnable=%02X\n",
gpe_register_info->base_gpe_number,
gpe_register_info->base_gpe_number +
(ACPI_GPE_REGISTER_WIDTH - 1),
status_reg, enable_reg,
gpe_register_info->enable_for_run,
gpe_register_info->enable_for_wake));
/* Check if there is anything active at all in this register */
enabled_status_byte = (u8)(status_reg & enable_reg);
if (!enabled_status_byte) {
/* No active GPEs in this register, move on */
continue;
}
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
/* Examine one GPE bit */
gpe_event_info =
&gpe_block->
event_info[((acpi_size) i *
ACPI_GPE_REGISTER_WIDTH) + j];
gpe_number =
j + gpe_register_info->base_gpe_number;
if (enabled_status_byte & (1 << j)) {
/* Invoke global event handler if present */
acpi_gpe_count++;
if (acpi_gbl_global_event_handler) {
acpi_gbl_global_event_handler
(ACPI_EVENT_TYPE_GPE,
gpe_device, gpe_number,
acpi_gbl_global_event_handler_context);
}
/* Found an active GPE */
if (ACPI_GPE_DISPATCH_TYPE
(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_RAW_HANDLER) {
/* Dispatch the event to a raw handler */
gpe_handler_info =
gpe_event_info->dispatch.
handler;
/*
* There is no protection around the namespace node
* and the GPE handler to ensure a safe destruction
* because:
* 1. The namespace node is expected to always
* exist after loading a table.
* 2. The GPE handler is expected to be flushed by
* acpi_os_wait_events_complete() before the
* destruction.
*/
acpi_os_release_lock
(acpi_gbl_gpe_lock, flags);
int_status |=
gpe_handler_info->
address(gpe_device,
gpe_number,
gpe_handler_info->
context);
flags =
acpi_os_acquire_lock
(acpi_gbl_gpe_lock);
} else {
/*
* Dispatch the event to a standard handler or
* method.
*/
int_status |=
acpi_ev_gpe_dispatch
(gpe_device, gpe_event_info,
gpe_number);
}
}
}
}
gpe_block = gpe_block->next;
}
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return (int_status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_asynch_execute_gpe_method
*
* PARAMETERS: Context (gpe_event_info) - Info for this GPE
*
* RETURN: None
*
* DESCRIPTION: Perform the actual execution of a GPE control method. This
* function is called from an invocation of acpi_os_execute and
* therefore does NOT execute at interrupt level - so that
* the control method itself is not executed in the context of
* an interrupt handler.
*
******************************************************************************/
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
{
struct acpi_gpe_event_info *gpe_event_info = context;
acpi_status status = AE_OK;
struct acpi_evaluate_info *info;
struct acpi_gpe_notify_info *notify;
ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
/* Do the correct dispatch - normal method or implicit notify */
switch (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)) {
case ACPI_GPE_DISPATCH_NOTIFY:
/*
* Implicit notify.
* Dispatch a DEVICE_WAKE notify to the appropriate handler.
* NOTE: the request is queued for execution after this method
* completes. The notify handlers are NOT invoked synchronously
* from this thread -- because handlers may in turn run other
* control methods.
*
* June 2012: Expand implicit notify mechanism to support
* notifies on multiple device objects.
*/
notify = gpe_event_info->dispatch.notify_list;
while (ACPI_SUCCESS(status) && notify) {
status =
acpi_ev_queue_notify_request(notify->device_node,
ACPI_NOTIFY_DEVICE_WAKE);
notify = notify->next;
}
break;
case ACPI_GPE_DISPATCH_METHOD:
/* Allocate the evaluation information block */
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
if (!info) {
status = AE_NO_MEMORY;
} else {
/*
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
* _Lxx/_Exx control method that corresponds to this GPE
*/
info->prefix_node =
gpe_event_info->dispatch.method_node;
info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info);
ACPI_FREE(info);
}
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"while evaluating GPE method [%4.4s]",
acpi_ut_get_node_name(gpe_event_info->
dispatch.
method_node)));
}
break;
default:
goto error_exit; /* Should never happen */
}
/* Defer enabling of GPE until all notify handlers are done */
status = acpi_os_execute(OSL_NOTIFY_HANDLER,
acpi_ev_asynch_enable_gpe, gpe_event_info);
if (ACPI_SUCCESS(status)) {
return_VOID;
}
error_exit:
acpi_ev_asynch_enable_gpe(gpe_event_info);
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_asynch_enable_gpe
*
* PARAMETERS: Context (gpe_event_info) - Info for this GPE
* Callback from acpi_os_execute
*
* RETURN: None
*
* DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
* complete (i.e., finish execution of Notify)
*
******************************************************************************/
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
{
struct acpi_gpe_event_info *gpe_event_info = context;
acpi_cpu_flags flags;
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
(void)acpi_ev_finish_gpe(gpe_event_info);
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return;
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_finish_gpe
*
* PARAMETERS: gpe_event_info - Info for this GPE
*
* RETURN: Status
*
* DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
* of a GPE method or a synchronous or asynchronous GPE handler.
*
******************************************************************************/
acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
acpi_status status;
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
ACPI_GPE_LEVEL_TRIGGERED) {
/*
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
return (status);
}
}
/*
* Enable this GPE, conditionally. This means that the GPE will
* only be physically enabled if the enable_mask bit is set
* in the event_info.
*/
(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_dispatch
*
* PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
* gpe_event_info - Info for this GPE
* gpe_number - Number relative to the parent GPE block
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
* DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
* or method (e.g. _Lxx/_Exx) handler.
*
* This function executes at interrupt level.
*
******************************************************************************/
u32
acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
{
acpi_status status;
u32 return_value;
ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
/*
* Always disable the GPE so that it does not keep firing before
* any asynchronous activity completes (either from the execution
* of a GPE method or an asynchronous GPE handler.)
*
* If there is no handler or method to run, just disable the
* GPE and leave it disabled permanently to prevent further such
* pointless events from firing.
*/
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE %02X", gpe_number));
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
/*
* If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
ACPI_GPE_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to clear GPE %02X",
gpe_number));
(void)acpi_hw_low_set_gpe(gpe_event_info,
ACPI_GPE_CONDITIONAL_ENABLE);
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
}
}
/*
* Dispatch the GPE to either an installed handler or the control
* method associated with this GPE (_Lxx or _Exx). If a handler
* exists, we invoke it and do not attempt to run the method.
* If there is neither a handler nor a method, leave the GPE
* disabled.
*/
switch (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)) {
case ACPI_GPE_DISPATCH_HANDLER:
/* Invoke the installed handler (at interrupt level) */
return_value =
gpe_event_info->dispatch.handler->address(gpe_device,
gpe_number,
gpe_event_info->
dispatch.handler->
context);
/* If requested, clear (if level-triggered) and reenable the GPE */
if (return_value & ACPI_REENABLE_GPE) {
(void)acpi_ev_finish_gpe(gpe_event_info);
}
break;
case ACPI_GPE_DISPATCH_METHOD:
case ACPI_GPE_DISPATCH_NOTIFY:
/*
* Execute the method associated with the GPE
* NOTE: Level-triggered GPEs are cleared after the method completes.
*/
status = acpi_os_execute(OSL_GPE_HANDLER,
acpi_ev_asynch_execute_gpe_method,
gpe_event_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to queue handler for GPE %02X - event disabled",
gpe_number));
}
break;
default:
/*
* No handler or method to run!
* 03/2010: This case should no longer be possible. We will not allow
* a GPE to be enabled if it has no handler or method.
*/
ACPI_ERROR((AE_INFO,
"No handler or method for GPE %02X, disabling event",
gpe_number));
break;
}
return_UINT32(ACPI_INTERRUPT_HANDLED);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,513 +0,0 @@
/******************************************************************************
*
* Module Name: evgpeblk - GPE block creation and initialization.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeblk")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status
acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
u32 interrupt_number);
static acpi_status
acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_gpe_block
*
* PARAMETERS: gpe_block - New GPE block
* interrupt_number - Xrupt to be associated with this
* GPE block
*
* RETURN: Status
*
* DESCRIPTION: Install new GPE block with mutex support
*
******************************************************************************/
static acpi_status
acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
u32 interrupt_number)
{
struct acpi_gpe_block_info *next_gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_block;
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(ev_install_gpe_block);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status =
acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Install the new block at the end of the list with lock */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt_block->gpe_block_list_head) {
next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (next_gpe_block->next) {
next_gpe_block = next_gpe_block->next;
}
next_gpe_block->next = gpe_block;
gpe_block->previous = next_gpe_block;
} else {
gpe_xrupt_block->gpe_block_list_head = gpe_block;
}
gpe_block->xrupt_block = gpe_xrupt_block;
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_block
*
* PARAMETERS: gpe_block - Existing GPE block
*
* RETURN: Status
*
* DESCRIPTION: Remove a GPE block
*
******************************************************************************/
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
{
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(ev_install_gpe_block);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Disable all GPEs in this block */
status =
acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
if (!gpe_block->previous && !gpe_block->next) {
/* This is the last gpe_block on this interrupt */
status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
} else {
/* Remove the block on this interrupt with lock */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_block->previous) {
gpe_block->previous->next = gpe_block->next;
} else {
gpe_block->xrupt_block->gpe_block_list_head =
gpe_block->next;
}
if (gpe_block->next) {
gpe_block->next->previous = gpe_block->previous;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
acpi_current_gpe_count -= gpe_block->gpe_count;
/* Free the gpe_block */
ACPI_FREE(gpe_block->register_info);
ACPI_FREE(gpe_block->event_info);
ACPI_FREE(gpe_block);
unlock_and_exit:
status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_info_blocks
*
* PARAMETERS: gpe_block - New GPE block
*
* RETURN: Status
*
* DESCRIPTION: Create the register_info and event_info blocks for this GPE block
*
******************************************************************************/
static acpi_status
acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
{
struct acpi_gpe_register_info *gpe_register_info = NULL;
struct acpi_gpe_event_info *gpe_event_info = NULL;
struct acpi_gpe_event_info *this_event;
struct acpi_gpe_register_info *this_register;
u32 i;
u32 j;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
/* Allocate the GPE register information block */
gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->
register_count *
sizeof(struct
acpi_gpe_register_info));
if (!gpe_register_info) {
ACPI_ERROR((AE_INFO,
"Could not allocate the GpeRegisterInfo table"));
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Allocate the GPE event_info block. There are eight distinct GPEs
* per register. Initialization to zeros is sufficient.
*/
gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->gpe_count *
sizeof(struct
acpi_gpe_event_info));
if (!gpe_event_info) {
ACPI_ERROR((AE_INFO,
"Could not allocate the GpeEventInfo table"));
status = AE_NO_MEMORY;
goto error_exit;
}
/* Save the new Info arrays in the GPE block */
gpe_block->register_info = gpe_register_info;
gpe_block->event_info = gpe_event_info;
/*
* Initialize the GPE Register and Event structures. A goal of these
* tables is to hide the fact that there are two separate GPE register
* sets in a given GPE hardware block, the status registers occupy the
* first half, and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
this_event = gpe_event_info;
for (i = 0; i < gpe_block->register_count; i++) {
/* Init the register_info for this GPE register (8 GPEs) */
this_register->base_gpe_number = (u16)
(gpe_block->block_base_number +
(i * ACPI_GPE_REGISTER_WIDTH));
this_register->status_address.address = gpe_block->address + i;
this_register->enable_address.address =
gpe_block->address + i + gpe_block->register_count;
this_register->status_address.space_id = gpe_block->space_id;
this_register->enable_address.space_id = gpe_block->space_id;
this_register->status_address.bit_width =
ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.bit_width =
ACPI_GPE_REGISTER_WIDTH;
this_register->status_address.bit_offset = 0;
this_register->enable_address.bit_offset = 0;
/* Init the event_info for each GPE within this register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
this_event->gpe_number =
(u8) (this_register->base_gpe_number + j);
this_event->register_info = this_register;
this_event++;
}
/* Disable all GPEs within this register */
status = acpi_hw_write(0x00, &this_register->enable_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
/* Clear any pending GPE events within this register */
status = acpi_hw_write(0xFF, &this_register->status_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
this_register++;
}
return_ACPI_STATUS(AE_OK);
error_exit:
if (gpe_register_info) {
ACPI_FREE(gpe_register_info);
}
if (gpe_event_info) {
ACPI_FREE(gpe_event_info);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_block
*
* PARAMETERS: gpe_device - Handle to the parent GPE block
* gpe_block_address - Address and space_ID
* register_count - Number of GPE register pairs in the block
* gpe_block_base_number - Starting GPE number for the block
* interrupt_number - H/W interrupt for the block
* return_gpe_block - Where the new block descriptor is returned
*
* RETURN: Status
*
* DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
* the block are disabled at exit.
* Note: Assumes namespace is locked.
*
******************************************************************************/
acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
u64 address,
u8 space_id,
u32 register_count,
u16 gpe_block_base_number,
u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block)
{
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_walk_info walk_info;
ACPI_FUNCTION_TRACE(ev_create_gpe_block);
if (!register_count) {
return_ACPI_STATUS(AE_OK);
}
/* Allocate a new GPE block */
gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
if (!gpe_block) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new GPE block */
gpe_block->address = address;
gpe_block->space_id = space_id;
gpe_block->node = gpe_device;
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
gpe_block->initialized = FALSE;
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
/*
* Create the register_info and event_info sub-structures
* Note: disables and clears all GPEs in the block
*/
status = acpi_ev_create_gpe_info_blocks(gpe_block);
if (ACPI_FAILURE(status)) {
ACPI_FREE(gpe_block);
return_ACPI_STATUS(status);
}
/* Install the new block in the global lists */
status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
if (ACPI_FAILURE(status)) {
ACPI_FREE(gpe_block->register_info);
ACPI_FREE(gpe_block->event_info);
ACPI_FREE(gpe_block);
return_ACPI_STATUS(status);
}
acpi_gbl_all_gpes_initialized = FALSE;
/* Find all GPE methods (_Lxx or_Exx) for this block */
walk_info.gpe_block = gpe_block;
walk_info.gpe_device = gpe_device;
walk_info.execute_by_owner_id = FALSE;
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
acpi_ev_match_gpe_method, NULL,
&walk_info, NULL);
/* Return the new block */
if (return_gpe_block) {
(*return_gpe_block) = gpe_block;
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
" Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
(u32)gpe_block->block_base_number,
(u32)(gpe_block->block_base_number +
(gpe_block->gpe_count - 1)),
gpe_device->name.ascii, gpe_block->register_count,
interrupt_number,
interrupt_number ==
acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
/* Update global count of currently available GPEs */
acpi_current_gpe_count += gpe_block->gpe_count;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_gpe_block
*
* PARAMETERS: acpi_gpe_callback
*
* RETURN: Status
*
* DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
* associated methods.
* Note: Assumes namespace is locked.
*
******************************************************************************/
acpi_status
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *ignored)
{
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
u32 gpe_enabled_count;
u32 gpe_index;
u32 i;
u32 j;
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
/*
* Ignore a null GPE block (e.g., if no GPE block 1 exists), and
* any GPE blocks that have been initialized already.
*/
if (!gpe_block || gpe_block->initialized) {
return_ACPI_STATUS(AE_OK);
}
/*
* Enable all GPEs that have a corresponding method and have the
* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
* must be enabled via the acpi_enable_gpe() interface.
*/
gpe_enabled_count = 0;
for (i = 0; i < gpe_block->register_count; i++) {
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
/* Get the info block for this particular GPE */
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
/*
* Ignore GPEs that have no corresponding _Lxx/_Exx method
* and GPEs that are used to wake the system
*/
if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_NONE)
|| (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_HANDLER)
|| (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_RAW_HANDLER)
|| (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
continue;
}
status = acpi_ev_add_gpe_reference(gpe_event_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not enable GPE 0x%02X",
gpe_index +
gpe_block->block_base_number));
continue;
}
gpe_enabled_count++;
}
}
if (gpe_enabled_count) {
ACPI_INFO((AE_INFO,
"Enabled %u GPEs in block %02X to %02X",
gpe_enabled_count, (u32)gpe_block->block_base_number,
(u32)(gpe_block->block_base_number +
(gpe_block->gpe_count - 1))));
}
gpe_block->initialized = TRUE;
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,446 +0,0 @@
/******************************************************************************
*
* Module Name: evgpeinit - System GPE initialization and update
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeinit")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*
* Note: History of _PRW support in ACPICA
*
* Originally (2000 - 2010), the GPE initialization code performed a walk of
* the entire namespace to execute the _PRW methods and detect all GPEs
* capable of waking the system.
*
* As of 10/2010, the _PRW method execution has been removed since it is
* actually unnecessary. The host OS must in fact execute all _PRW methods
* in order to identify the device/power-resource dependencies. We now put
* the onus on the host OS to identify the wake GPEs as part of this process
* and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This
* not only reduces the complexity of the ACPICA initialization code, but in
* some cases (on systems with very large namespaces) it should reduce the
* kernel boot time as well.
*/
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_initialize
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks
*
******************************************************************************/
acpi_status acpi_ev_gpe_initialize(void)
{
u32 register_count0 = 0;
u32 register_count1 = 0;
u32 gpe_number_max = 0;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_gpe_initialize);
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
"Initializing General Purpose Events (GPEs):\n"));
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Initialize the GPE Block(s) defined in the FADT
*
* Why the GPE register block lengths are divided by 2: From the ACPI
* Spec, section "General-Purpose Event Registers", we have:
*
* "Each register block contains two registers of equal length
* GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
* GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
* The length of the GPE1_STS and GPE1_EN registers is equal to
* half the GPE1_LEN. If a generic register block is not supported
* then its respective block pointer and block length values in the
* FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
* to be the same size."
*/
/*
* Determine the maximum GPE number for this machine.
*
* Note: both GPE0 and GPE1 are optional, and either can exist without
* the other.
*
* If EITHER the register length OR the block address are zero, then that
* particular block is not supported.
*/
if (acpi_gbl_FADT.gpe0_block_length &&
acpi_gbl_FADT.xgpe0_block.address) {
/* GPE block 0 exists (has both length and address > 0) */
register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2);
gpe_number_max =
(register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
/* Install GPE Block 0 */
status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_FADT.xgpe0_block.
address,
acpi_gbl_FADT.xgpe0_block.
space_id, register_count0, 0,
acpi_gbl_FADT.sci_interrupt,
&acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not create GPE Block 0"));
}
}
if (acpi_gbl_FADT.gpe1_block_length &&
acpi_gbl_FADT.xgpe1_block.address) {
/* GPE block 1 exists (has both length and address > 0) */
register_count1 = (u16)(acpi_gbl_FADT.gpe1_block_length / 2);
/* Check for GPE0/GPE1 overlap (if both banks exist) */
if ((register_count0) &&
(gpe_number_max >= acpi_gbl_FADT.gpe1_base)) {
ACPI_ERROR((AE_INFO,
"GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
"(GPE %u to %u) - Ignoring GPE1",
gpe_number_max, acpi_gbl_FADT.gpe1_base,
acpi_gbl_FADT.gpe1_base +
((register_count1 *
ACPI_GPE_REGISTER_WIDTH) - 1)));
/* Ignore GPE1 block by setting the register count to zero */
register_count1 = 0;
} else {
/* Install GPE Block 1 */
status =
acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_FADT.xgpe1_block.
address,
acpi_gbl_FADT.xgpe1_block.
space_id, register_count1,
acpi_gbl_FADT.gpe1_base,
acpi_gbl_FADT.
sci_interrupt,
&acpi_gbl_gpe_fadt_blocks
[1]);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not create GPE Block 1"));
}
/*
* GPE0 and GPE1 do not have to be contiguous in the GPE number
* space. However, GPE0 always starts at GPE number zero.
*/
gpe_number_max = acpi_gbl_FADT.gpe1_base +
((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
}
}
/* Exit if there are no GPE registers */
if ((register_count0 + register_count1) == 0) {
/* GPEs are not required by ACPI, this is OK */
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"There are no GPE blocks defined in the FADT\n"));
status = AE_OK;
goto cleanup;
}
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_update_gpes
*
* PARAMETERS: table_owner_id - ID of the newly-loaded ACPI table
*
* RETURN: None
*
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
* result of a Load() or load_table() operation. If new GPE
* methods have been installed, register the new methods.
*
******************************************************************************/
void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_walk_info walk_info;
acpi_status status = AE_OK;
/*
* Find any _Lxx/_Exx GPE methods that have just been loaded.
*
* Any GPEs that correspond to new _Lxx/_Exx methods are immediately
* enabled.
*
* Examine the namespace underneath each gpe_device within the
* gpe_block lists.
*/
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return;
}
walk_info.count = 0;
walk_info.owner_id = table_owner_id;
walk_info.execute_by_owner_id = TRUE;
/* Walk the interrupt level descriptor list */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
/* Walk all Gpe Blocks attached to this interrupt level */
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
walk_info.gpe_block = gpe_block;
walk_info.gpe_device = gpe_block->node;
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD,
walk_info.gpe_device,
ACPI_UINT32_MAX,
ACPI_NS_WALK_NO_UNLOCK,
acpi_ev_match_gpe_method,
NULL, &walk_info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While decoding _Lxx/_Exx methods"));
}
gpe_block = gpe_block->next;
}
gpe_xrupt_info = gpe_xrupt_info->next;
}
if (walk_info.count) {
ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count));
}
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return;
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_match_gpe_method
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
* control method under the _GPE portion of the namespace.
* Extract the name and GPE type from the object, saving this
* information for quick lookup during GPE dispatch. Allows a
* per-owner_id evaluation if execute_by_owner_id is TRUE in the
* walk_info parameter block.
*
* The name of each GPE control method is of the form:
* "_Lxx" or "_Exx", where:
* L - means that the GPE is level triggered
* E - means that the GPE is edge triggered
* xx - is the GPE number [in HEX]
*
* If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
* with that owner.
*
******************************************************************************/
acpi_status
acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
struct acpi_namespace_node *method_node =
ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
struct acpi_gpe_walk_info *walk_info =
ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
struct acpi_gpe_event_info *gpe_event_info;
u32 gpe_number;
char name[ACPI_NAME_SIZE + 1];
u8 type;
ACPI_FUNCTION_TRACE(ev_match_gpe_method);
/* Check if requested owner_id matches this owner_id */
if ((walk_info->execute_by_owner_id) &&
(method_node->owner_id != walk_info->owner_id)) {
return_ACPI_STATUS(AE_OK);
}
/*
* Match and decode the _Lxx and _Exx GPE method names
*
* 1) Extract the method name and null terminate it
*/
ACPI_MOVE_32_TO_32(name, &method_node->name.integer);
name[ACPI_NAME_SIZE] = 0;
/* 2) Name must begin with an underscore */
if (name[0] != '_') {
return_ACPI_STATUS(AE_OK); /* Ignore this method */
}
/*
* 3) Edge/Level determination is based on the 2nd character
* of the method name
*/
switch (name[1]) {
case 'L':
type = ACPI_GPE_LEVEL_TRIGGERED;
break;
case 'E':
type = ACPI_GPE_EDGE_TRIGGERED;
break;
default:
/* Unknown method type, just ignore it */
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Ignoring unknown GPE method type: %s "
"(name not of form _Lxx or _Exx)", name));
return_ACPI_STATUS(AE_OK);
}
/* 4) The last two characters of the name are the hex GPE Number */
gpe_number = strtoul(&name[2], NULL, 16);
if (gpe_number == ACPI_UINT32_MAX) {
/* Conversion failed; invalid method, just ignore it */
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Could not extract GPE number from name: %s "
"(name is not of form _Lxx or _Exx)", name));
return_ACPI_STATUS(AE_OK);
}
/* Ensure that we have a valid GPE number for this GPE block */
gpe_event_info =
acpi_ev_low_get_gpe_info(gpe_number, walk_info->gpe_block);
if (!gpe_event_info) {
/*
* This gpe_number is not valid for this GPE block, just ignore it.
* However, it may be valid for a different GPE block, since GPE0
* and GPE1 methods both appear under \_GPE.
*/
return_ACPI_STATUS(AE_OK);
}
if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_HANDLER) ||
(ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_RAW_HANDLER)) {
/* If there is already a handler, ignore this GPE method */
return_ACPI_STATUS(AE_OK);
}
if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_METHOD) {
/*
* If there is already a method, ignore this method. But check
* for a type mismatch (if both the _Lxx AND _Exx exist)
*/
if (type != (gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
ACPI_ERROR((AE_INFO,
"For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
gpe_number, gpe_number, gpe_number));
}
return_ACPI_STATUS(AE_OK);
}
/* Disable the GPE in case it's been enabled already. */
(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
/*
* Add the GPE information from above to the gpe_event_info block for
* use during dispatch of this GPE.
*/
gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
gpe_event_info->dispatch.method_node = method_node;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Registered GPE method %s as GPE number 0x%.2X\n",
name, gpe_number));
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,359 +0,0 @@
/******************************************************************************
*
* Module Name: evgpeutil - GPE utilities
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeutil")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_ev_walk_gpe_list
*
* PARAMETERS: gpe_walk_callback - Routine called for each GPE block
* context - Value passed to callback
*
* RETURN: Status
*
* DESCRIPTION: Walk the GPE lists.
*
******************************************************************************/
acpi_status
acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context)
{
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
acpi_status status = AE_OK;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(ev_walk_gpe_list);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Walk the interrupt level descriptor list */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
/* Walk all Gpe Blocks attached to this interrupt level */
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
/* One callback per GPE block */
status =
gpe_walk_callback(gpe_xrupt_info, gpe_block,
context);
if (ACPI_FAILURE(status)) {
if (status == AE_CTRL_END) { /* Callback abort */
status = AE_OK;
}
goto unlock_and_exit;
}
gpe_block = gpe_block->next;
}
gpe_xrupt_info = gpe_xrupt_info->next;
}
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_device
*
* PARAMETERS: GPE_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
* block device. NULL if the GPE is one of the FADT-defined GPEs.
*
******************************************************************************/
acpi_status
acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context)
{
struct acpi_gpe_device_info *info = context;
/* Increment Index by the number of GPEs in this block */
info->next_block_base_index += gpe_block->gpe_count;
if (info->index < info->next_block_base_index) {
/*
* The GPE index is within this block, get the node. Leave the node
* NULL for the FADT-defined GPEs
*/
if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
info->gpe_device = gpe_block->node;
}
info->status = AE_OK;
return (AE_CTRL_END);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
* PARAMETERS: interrupt_number - Interrupt for a GPE block
* gpe_xrupt_block - Where the block is returned
*
* RETURN: Status
*
* DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
* block per unique interrupt level used for GPEs. Should be
* called only when the GPE lists are semaphore locked and not
* subject to change.
*
******************************************************************************/
acpi_status
acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
struct acpi_gpe_xrupt_info ** gpe_xrupt_block)
{
struct acpi_gpe_xrupt_info *next_gpe_xrupt;
struct acpi_gpe_xrupt_info *gpe_xrupt;
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block);
/* No need for lock since we are not changing any list elements here */
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt) {
if (next_gpe_xrupt->interrupt_number == interrupt_number) {
*gpe_xrupt_block = next_gpe_xrupt;
return_ACPI_STATUS(AE_OK);
}
next_gpe_xrupt = next_gpe_xrupt->next;
}
/* Not found, must allocate a new xrupt descriptor */
gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
gpe_xrupt->interrupt_number = interrupt_number;
/* Install new interrupt descriptor with spin lock */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (acpi_gbl_gpe_xrupt_list_head) {
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt->next) {
next_gpe_xrupt = next_gpe_xrupt->next;
}
next_gpe_xrupt->next = gpe_xrupt;
gpe_xrupt->previous = next_gpe_xrupt;
} else {
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Install new interrupt handler if not SCI_INT */
if (interrupt_number != acpi_gbl_FADT.sci_interrupt) {
status = acpi_os_install_interrupt_handler(interrupt_number,
acpi_ev_gpe_xrupt_handler,
gpe_xrupt);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not install GPE interrupt handler at level 0x%X",
interrupt_number));
return_ACPI_STATUS(status);
}
}
*gpe_xrupt_block = gpe_xrupt;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_xrupt
*
* PARAMETERS: gpe_xrupt - A GPE interrupt info block
*
* RETURN: Status
*
* DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated
* interrupt handler if not the SCI interrupt.
*
******************************************************************************/
acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
{
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt);
/* We never want to remove the SCI interrupt handler */
if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) {
gpe_xrupt->gpe_block_list_head = NULL;
return_ACPI_STATUS(AE_OK);
}
/* Disable this interrupt */
status =
acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
acpi_ev_gpe_xrupt_handler);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Unlink the interrupt block with lock */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt->previous) {
gpe_xrupt->previous->next = gpe_xrupt->next;
} else {
/* No previous, update list head */
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next;
}
if (gpe_xrupt->next) {
gpe_xrupt->next->previous = gpe_xrupt->previous;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Free the block */
ACPI_FREE(gpe_xrupt);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_handlers
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Delete all Handler objects found in the GPE data structs.
* Used only prior to termination.
*
******************************************************************************/
acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context)
{
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_gpe_notify_info *notify;
struct acpi_gpe_notify_info *next;
u32 i;
u32 j;
ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
gpe_event_info = &gpe_block->event_info[((acpi_size) i *
ACPI_GPE_REGISTER_WIDTH)
+ j];
if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_HANDLER) ||
(ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_RAW_HANDLER)) {
/* Delete an installed handler block */
ACPI_FREE(gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
} else if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)
== ACPI_GPE_DISPATCH_NOTIFY) {
/* Delete the implicit notification device list */
notify = gpe_event_info->dispatch.notify_list;
while (notify) {
next = notify->next;
ACPI_FREE(notify);
notify = next;
}
gpe_event_info->dispatch.notify_list = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
}
}
}
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,536 +0,0 @@
/******************************************************************************
*
* Module Name: evhandler - Support for Address Space handlers
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evhandler")
/* Local prototypes */
static acpi_status
acpi_ev_install_handler(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
/* These are the address spaces that will get default handlers */
u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
ACPI_ADR_SPACE_SYSTEM_MEMORY,
ACPI_ADR_SPACE_SYSTEM_IO,
ACPI_ADR_SPACE_PCI_CONFIG,
ACPI_ADR_SPACE_DATA_TABLE
};
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_region_handlers
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Installs the core subsystem default address space handlers.
*
******************************************************************************/
acpi_status acpi_ev_install_region_handlers(void)
{
acpi_status status;
u32 i;
ACPI_FUNCTION_TRACE(ev_install_region_handlers);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* All address spaces (PCI Config, EC, SMBus) are scope dependent and
* registration must occur for a specific device.
*
* In the case of the system memory and IO address spaces there is
* currently no device associated with the address space. For these we
* use the root.
*
* We install the default PCI config space handler at the root so that
* this space is immediately available even though the we have not
* enumerated all the PCI Root Buses yet. This is to conform to the ACPI
* specification which states that the PCI config space must be always
* available -- even though we are nowhere near ready to find the PCI root
* buses at this point.
*
* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
* has already been installed (via acpi_install_address_space_handler).
* Similar for AE_SAME_HANDLER.
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
status = acpi_ev_install_space_handler(acpi_gbl_root_node,
acpi_gbl_default_address_spaces
[i],
ACPI_DEFAULT_HANDLER,
NULL, NULL);
switch (status) {
case AE_OK:
case AE_SAME_HANDLER:
case AE_ALREADY_EXISTS:
/* These exceptions are all OK */
status = AE_OK;
break;
default:
goto unlock_and_exit;
}
}
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_has_default_handler
*
* PARAMETERS: node - Namespace node for the device
* space_id - The address space ID
*
* RETURN: TRUE if default handler is installed, FALSE otherwise
*
* DESCRIPTION: Check if the default handler is installed for the requested
* space ID.
*
******************************************************************************/
u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
acpi_adr_space_type space_id)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
/* Must have an existing internal object */
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
handler_obj = obj_desc->device.handler;
/* Walk the linked list of handlers for this object */
while (handler_obj) {
if (handler_obj->address_space.space_id == space_id) {
if (handler_obj->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
return (TRUE);
}
}
handler_obj = handler_obj->address_space.next;
}
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_handler
*
* PARAMETERS: walk_namespace callback
*
* DESCRIPTION: This routine installs an address handler into objects that are
* of type Region or Device.
*
* If the Object is a Device, and the device has a handler of
* the same type then the search is terminated in that branch.
*
* This is because the existing handler is closer in proximity
* to any more regions than the one we are trying to install.
*
******************************************************************************/
static acpi_status
acpi_ev_install_handler(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
union acpi_operand_object *handler_obj;
union acpi_operand_object *next_handler_obj;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_NAME(ev_install_handler);
handler_obj = (union acpi_operand_object *)context;
/* Parameter validation */
if (!handler_obj) {
return (AE_OK);
}
/* Convert and validate the device handle */
node = acpi_ns_validate_handle(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
/*
* We only care about regions and objects that are allowed to have
* address space handlers
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
return (AE_OK);
}
/* Devices are handled different than regions */
if (obj_desc->common.type == ACPI_TYPE_DEVICE) {
/* Check if this Device already has a handler for this address space */
next_handler_obj = obj_desc->device.handler;
while (next_handler_obj) {
/* Found a handler, is it for the same address space? */
if (next_handler_obj->address_space.space_id ==
handler_obj->address_space.space_id) {
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Found handler for region [%s] in device %p(%p) "
"handler %p\n",
acpi_ut_get_region_name
(handler_obj->address_space.
space_id), obj_desc,
next_handler_obj,
handler_obj));
/*
* Since the object we found it on was a device, then it
* means that someone has already installed a handler for
* the branch of the namespace from this device on. Just
* bail out telling the walk routine to not traverse this
* branch. This preserves the scoping rule for handlers.
*/
return (AE_CTRL_DEPTH);
}
/* Walk the linked list of handlers attached to this device */
next_handler_obj = next_handler_obj->address_space.next;
}
/*
* As long as the device didn't have a handler for this space we
* don't care about it. We just ignore it and proceed.
*/
return (AE_OK);
}
/* Object is a Region */
if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
/* This region is for a different address space, just ignore it */
return (AE_OK);
}
/*
* Now we have a region and it is for the handler's address space type.
*
* First disconnect region for any previous handler (if any)
*/
acpi_ev_detach_region(obj_desc, FALSE);
/* Connect the region to the new handler */
status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_space_handler
*
* PARAMETERS: node - Namespace node for the device
* space_id - The address space ID
* handler - Address of the handler
* setup - Address of the setup function
* context - Value passed to the handler on each access
*
* RETURN: Status
*
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
* Assumes namespace is locked
*
******************************************************************************/
acpi_status
acpi_ev_install_space_handler(struct acpi_namespace_node * node,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler,
acpi_adr_space_setup setup, void *context)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
acpi_status status;
acpi_object_type type;
u8 flags = 0;
ACPI_FUNCTION_TRACE(ev_install_space_handler);
/*
* This registration is valid for only the types below and the root. This
* is where the default handlers get placed.
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
(node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (handler == ACPI_DEFAULT_HANDLER) {
flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
handler = acpi_ex_system_memory_space_handler;
setup = acpi_ev_system_memory_region_setup;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
handler = acpi_ex_system_io_space_handler;
setup = acpi_ev_io_space_region_setup;
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
handler = acpi_ex_pci_config_space_handler;
setup = acpi_ev_pci_config_region_setup;
break;
case ACPI_ADR_SPACE_CMOS:
handler = acpi_ex_cmos_space_handler;
setup = acpi_ev_cmos_region_setup;
break;
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
handler = acpi_ex_pci_bar_space_handler;
setup = acpi_ev_pci_bar_region_setup;
break;
case ACPI_ADR_SPACE_DATA_TABLE:
handler = acpi_ex_data_table_space_handler;
setup = NULL;
break;
default:
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
}
/* If the caller hasn't specified a setup routine, use the default */
if (!setup) {
setup = acpi_ev_default_region_setup;
}
/* Check for an existing internal object */
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/*
* The attached device object already exists. Make sure the handler
* is not already installed.
*/
handler_obj = obj_desc->device.handler;
/* Walk the handler list for this device */
while (handler_obj) {
/* Same space_id indicates a handler already installed */
if (handler_obj->address_space.space_id == space_id) {
if (handler_obj->address_space.handler ==
handler) {
/*
* It is (relatively) OK to attempt to install the SAME
* handler twice. This can easily happen with the
* PCI_Config space.
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
} else {
/* A handler is already installed */
status = AE_ALREADY_EXISTS;
}
goto unlock_and_exit;
}
/* Walk the linked list of handlers */
handler_obj = handler_obj->address_space.next;
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Creating object on Device %p while installing handler\n",
node));
/* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
} else {
type = node->type;
}
obj_desc = acpi_ut_create_internal_object(type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Init new descriptor */
obj_desc->common.type = (u8)type;
/* Attach the new object to the Node */
status = acpi_ns_attach_object(node, obj_desc, type);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
acpi_ut_get_region_name(space_id), space_id,
acpi_ut_get_node_name(node), node, obj_desc));
/*
* Install the handler
*
* At this point there is no existing handler. Just allocate the object
* for the handler and link it into the list.
*/
handler_obj =
acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Init handler obj */
handler_obj->address_space.space_id = (u8)space_id;
handler_obj->address_space.handler_flags = flags;
handler_obj->address_space.region_list = NULL;
handler_obj->address_space.node = node;
handler_obj->address_space.handler = handler;
handler_obj->address_space.context = context;
handler_obj->address_space.setup = setup;
/* Install at head of Device.address_space list */
handler_obj->address_space.next = obj_desc->device.handler;
/*
* The Device object is the first reference on the handler_obj.
* Each region that uses the handler adds a reference.
*/
obj_desc->device.handler = handler_obj;
/*
* Walk the namespace finding all of the regions this
* handler will manage.
*
* Start at the device and search the branch toward
* the leaf nodes until either the leaf is encountered or
* a device is detected that has an address handler of the
* same type.
*
* In either case, back up and search down the remainder
* of the branch
*/
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK,
acpi_ev_install_handler, NULL,
handler_obj, NULL);
unlock_and_exit:
return_ACPI_STATUS(status);
}

View File

@@ -1,299 +0,0 @@
/******************************************************************************
*
* Module Name: evmisc - Miscellaneous event manager support functions
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evmisc")
/* Local prototypes */
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
/*******************************************************************************
*
* FUNCTION: acpi_ev_is_notify_object
*
* PARAMETERS: node - Node to check
*
* RETURN: TRUE if notifies allowed on this object
*
* DESCRIPTION: Check type of node for a object that supports notifies.
*
* TBD: This could be replaced by a flag bit in the node.
*
******************************************************************************/
u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
{
switch (node->type) {
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
/*
* These are the ONLY objects that can receive ACPI notifications
*/
return (TRUE);
default:
return (FALSE);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_queue_notify_request
*
* PARAMETERS: node - NS node for the notified object
* notify_value - Value from the Notify() request
*
* RETURN: Status
*
* DESCRIPTION: Dispatch a device notification event to a previously
* installed handler.
*
******************************************************************************/
acpi_status
acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
u32 notify_value)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_list_head = NULL;
union acpi_generic_state *info;
u8 handler_list_id = 0;
acpi_status status = AE_OK;
ACPI_FUNCTION_NAME(ev_queue_notify_request);
/* Are Notifies allowed on this object? */
if (!acpi_ev_is_notify_object(node)) {
return (AE_TYPE);
}
/* Get the correct notify list type (System or Device) */
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
} else {
handler_list_id = ACPI_DEVICE_HANDLER_LIST;
}
/* Get the notify object attached to the namespace Node */
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* We have an attached object, Get the correct handler list */
handler_list_head =
obj_desc->common_notify.notify_list[handler_list_id];
}
/*
* If there is no notify handler (Global or Local)
* for this object, just ignore the notify
*/
if (!acpi_gbl_global_notify[handler_list_id].handler
&& !handler_list_head) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
acpi_ut_get_node_name(node), notify_value,
node));
return (AE_OK);
}
/* Setup notify info and schedule the notify dispatcher */
info = acpi_ut_create_generic_state();
if (!info) {
return (AE_NO_MEMORY);
}
info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
info->notify.node = node;
info->notify.value = (u16)notify_value;
info->notify.handler_list_id = handler_list_id;
info->notify.handler_list_head = handler_list_head;
info->notify.global = &acpi_gbl_global_notify[handler_list_id];
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type), notify_value,
acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
node));
status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
info);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_generic_state(info);
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_notify_dispatch
*
* PARAMETERS: context - To be passed to the notify handler
*
* RETURN: None.
*
* DESCRIPTION: Dispatch a device notification event to a previously
* installed handler.
*
******************************************************************************/
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
{
union acpi_generic_state *info = (union acpi_generic_state *)context;
union acpi_operand_object *handler_obj;
ACPI_FUNCTION_ENTRY();
/* Invoke a global notify handler if installed */
if (info->notify.global->handler) {
info->notify.global->handler(info->notify.node,
info->notify.value,
info->notify.global->context);
}
/* Now invoke the local notify handler(s) if any are installed */
handler_obj = info->notify.handler_list_head;
while (handler_obj) {
handler_obj->notify.handler(info->notify.node,
info->notify.value,
handler_obj->notify.context);
handler_obj =
handler_obj->notify.next[info->notify.handler_list_id];
}
/* All done with the info object */
acpi_ut_delete_generic_state(info);
}
#if (!ACPI_REDUCED_HARDWARE)
/******************************************************************************
*
* FUNCTION: acpi_ev_terminate
*
* PARAMETERS: none
*
* RETURN: none
*
* DESCRIPTION: Disable events and free memory allocated for table storage.
*
******************************************************************************/
void acpi_ev_terminate(void)
{
u32 i;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_terminate);
if (acpi_gbl_events_initialized) {
/*
* Disable all event-related functionality. In all cases, on error,
* print a message but obviously we don't abort.
*/
/* Disable all fixed events */
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
status = acpi_disable_event(i, 0);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not disable fixed event %u",
(u32) i));
}
}
/* Disable all GPEs in all GPE blocks */
status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
status = acpi_ev_remove_global_lock_handler();
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not remove Global Lock handler"));
}
acpi_gbl_events_initialized = FALSE;
}
/* Remove SCI handlers */
status = acpi_ev_remove_all_sci_handlers();
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
}
/* Deallocate all handler objects installed within GPE info structs */
status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
/* Return to original mode if necessary */
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
status = acpi_disable();
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
}
}
return_VOID;
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,809 +0,0 @@
/******************************************************************************
*
* Module Name: evregion - Operation Region support
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evregion")
extern u8 acpi_gbl_default_address_spaces[];
/* Local prototypes */
static void
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_op_regions
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Execute _REG methods for all Operation Regions that have
* an installed default region handler.
*
******************************************************************************/
acpi_status acpi_ev_initialize_op_regions(void)
{
acpi_status status;
u32 i;
ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Run the _REG methods for op_regions in each default address space */
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
/*
* Make sure the installed handler is the DEFAULT handler. If not the
* default, the _REG methods will have already been run (when the
* handler was installed)
*/
if (acpi_ev_has_default_handler(acpi_gbl_root_node,
acpi_gbl_default_address_spaces
[i])) {
status =
acpi_ev_execute_reg_methods(acpi_gbl_root_node,
acpi_gbl_default_address_spaces
[i]);
}
}
acpi_gbl_reg_methods_executed = TRUE;
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_address_space_dispatch
*
* PARAMETERS: region_obj - Internal region object
* field_obj - Corresponding field. Can be NULL.
* function - Read or Write operation
* region_offset - Where in the region to read or write
* bit_width - Field width in bits (8, 16, 32, or 64)
* value - Pointer to in or out value, must be
* a full 64-bit integer
*
* RETURN: Status
*
* DESCRIPTION: Dispatch an address space or operation region access to
* a previously installed handler.
*
******************************************************************************/
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *field_obj,
u32 function,
u32 region_offset, u32 bit_width, u64 *value)
{
acpi_status status;
acpi_adr_space_handler handler;
acpi_adr_space_setup region_setup;
union acpi_operand_object *handler_desc;
union acpi_operand_object *region_obj2;
void *region_context = NULL;
struct acpi_connection_info *context;
acpi_physical_address address;
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Ensure that there is a handler associated with this region */
handler_desc = region_obj->region.handler;
if (!handler_desc) {
ACPI_ERROR((AE_INFO,
"No handler for Region [%4.4s] (%p) [%s]",
acpi_ut_get_node_name(region_obj->region.node),
region_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
context = handler_desc->address_space.context;
/*
* It may be the case that the region has never been initialized.
* Some types of regions require special init code
*/
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
/* This region has not been initialized yet, do it */
region_setup = handler_desc->address_space.setup;
if (!region_setup) {
/* No initialization routine, exit with error */
ACPI_ERROR((AE_INFO,
"No init routine for region(%p) [%s]",
region_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* We must exit the interpreter because the region setup will
* potentially execute control methods (for example, the _REG method
* for this region)
*/
acpi_ex_exit_interpreter();
status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
context, &region_context);
/* Re-enter the interpreter */
acpi_ex_enter_interpreter();
/* Check for failure of the Region Setup */
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"During region initialization: [%s]",
acpi_ut_get_region_name(region_obj->
region.
space_id)));
return_ACPI_STATUS(status);
}
/* Region initialization may have been completed by region_setup */
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
/*
* Save the returned context for use in all accesses to
* the handler for this particular region
*/
if (!(region_obj2->extra.region_context)) {
region_obj2->extra.region_context =
region_context;
}
}
}
/* We have everything we need, we can invoke the address space handler */
handler = handler_desc->address_space.handler;
address = (region_obj->region.address + region_offset);
/*
* Special handling for generic_serial_bus and general_purpose_io:
* There are three extra parameters that must be passed to the
* handler via the context:
* 1) Connection buffer, a resource template from Connection() op
* 2) Length of the above buffer
* 3) Actual access length from the access_as() op
*
* In addition, for general_purpose_io, the Address and bit_width fields
* are defined as follows:
* 1) Address is the pin number index of the field (bit offset from
* the previous Connection)
* 2) bit_width is the actual bit length of the field (number of pins)
*/
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
context && field_obj) {
/* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer;
context->length = field_obj->field.resource_length;
context->access_length = field_obj->field.access_length;
}
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
context && field_obj) {
/* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer;
context->length = field_obj->field.resource_length;
context->access_length = field_obj->field.access_length;
address = field_obj->field.pin_number_index;
bit_width = field_obj->field.bit_length;
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
&region_obj->region.handler->address_space, handler,
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(region_obj->region.
space_id)));
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
acpi_ex_exit_interpreter();
}
/* Call the handler */
status = handler(function, address, bit_width, value, context,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
acpi_ut_get_region_name(region_obj->region.
space_id)));
}
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
acpi_ex_enter_interpreter();
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_detach_region
*
* PARAMETERS: region_obj - Region Object
* acpi_ns_is_locked - Namespace Region Already Locked?
*
* RETURN: None
*
* DESCRIPTION: Break the association between the handler and the region
* this is a two way association.
*
******************************************************************************/
void
acpi_ev_detach_region(union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked)
{
union acpi_operand_object *handler_obj;
union acpi_operand_object *obj_desc;
union acpi_operand_object *start_desc;
union acpi_operand_object **last_obj_ptr;
acpi_adr_space_setup region_setup;
void **region_context;
union acpi_operand_object *region_obj2;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_detach_region);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_VOID;
}
region_context = &region_obj2->extra.region_context;
/* Get the address handler from the region object */
handler_obj = region_obj->region.handler;
if (!handler_obj) {
/* This region has no handler, all done */
return_VOID;
}
/* Find this region in the handler's list */
obj_desc = handler_obj->address_space.region_list;
start_desc = obj_desc;
last_obj_ptr = &handler_obj->address_space.region_list;
while (obj_desc) {
/* Is this the correct Region? */
if (obj_desc == region_obj) {
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Removing Region %p from address handler %p\n",
region_obj, handler_obj));
/* This is it, remove it from the handler's list */
*last_obj_ptr = obj_desc->region.next;
obj_desc->region.next = NULL; /* Must clear field */
if (acpi_ns_is_locked) {
status =
acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Now stop region accesses by executing the _REG method */
status =
acpi_ev_execute_reg_method(region_obj,
ACPI_REG_DISCONNECT);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"from region _REG, [%s]",
acpi_ut_get_region_name
(region_obj->region.space_id)));
}
if (acpi_ns_is_locked) {
status =
acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/*
* If the region has been activated, call the setup handler with
* the deactivate notification
*/
if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
region_setup = handler_obj->address_space.setup;
status =
region_setup(region_obj,
ACPI_REGION_DEACTIVATE,
handler_obj->address_space.
context, region_context);
/*
* region_context should have been released by the deactivate
* operation. We don't need access to it anymore here.
*/
if (region_context) {
*region_context = NULL;
}
/* Init routine may fail, Just ignore errors */
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"from region handler - deactivate, [%s]",
acpi_ut_get_region_name
(region_obj->region.
space_id)));
}
region_obj->region.flags &=
~(AOPOBJ_SETUP_COMPLETE);
}
/*
* Remove handler reference in the region
*
* NOTE: this doesn't mean that the region goes away, the region
* is just inaccessible as indicated to the _REG method
*
* If the region is on the handler's list, this must be the
* region's handler
*/
region_obj->region.handler = NULL;
acpi_ut_remove_reference(handler_obj);
return_VOID;
}
/* Walk the linked list of handlers */
last_obj_ptr = &obj_desc->region.next;
obj_desc = obj_desc->region.next;
/* Prevent infinite loop if list is corrupted */
if (obj_desc == start_desc) {
ACPI_ERROR((AE_INFO,
"Circular handler list in region object %p",
region_obj));
return_VOID;
}
}
/* If we get here, the region was not in the handler's region list */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Cannot remove region %p from address handler %p\n",
region_obj, handler_obj));
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_attach_region
*
* PARAMETERS: handler_obj - Handler Object
* region_obj - Region Object
* acpi_ns_is_locked - Namespace Region Already Locked?
*
* RETURN: None
*
* DESCRIPTION: Create the association between the handler and the region
* this is a two way association.
*
******************************************************************************/
acpi_status
acpi_ev_attach_region(union acpi_operand_object *handler_obj,
union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked)
{
ACPI_FUNCTION_TRACE(ev_attach_region);
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Adding Region [%4.4s] %p to address handler %p [%s]\n",
acpi_ut_get_node_name(region_obj->region.node),
region_obj, handler_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
/* Link this region to the front of the handler's list */
region_obj->region.next = handler_obj->address_space.region_list;
handler_obj->address_space.region_list = region_obj;
/* Install the region's handler */
if (region_obj->region.handler) {
return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
region_obj->region.handler = handler_obj;
acpi_ut_add_reference(handler_obj);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_method
*
* PARAMETERS: region_obj - Region object
* function - Passed to _REG: On (1) or Off (0)
*
* RETURN: Status
*
* DESCRIPTION: Execute _REG method for a region
*
******************************************************************************/
acpi_status
acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
{
struct acpi_evaluate_info *info;
union acpi_operand_object *args[3];
union acpi_operand_object *region_obj2;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_execute_reg_method);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
if (region_obj2->extra.method_REG == NULL) {
return_ACPI_STATUS(AE_OK);
}
/* Allocate and initialize the evaluation information block */
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
if (!info) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
info->prefix_node = region_obj2->extra.method_REG;
info->relative_pathname = NULL;
info->parameters = args;
info->flags = ACPI_IGNORE_RETURN_VALUE;
/*
* The _REG method has two arguments:
*
* arg0 - Integer:
* Operation region space ID Same value as region_obj->Region.space_id
*
* arg1 - Integer:
* connection status 1 for connecting the handler, 0 for disconnecting
* the handler (Passed as a parameter)
*/
args[0] =
acpi_ut_create_integer_object((u64)region_obj->region.space_id);
if (!args[0]) {
status = AE_NO_MEMORY;
goto cleanup1;
}
args[1] = acpi_ut_create_integer_object((u64)function);
if (!args[1]) {
status = AE_NO_MEMORY;
goto cleanup2;
}
args[2] = NULL; /* Terminate list */
/* Execute the method, no return value */
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_METHOD, info->prefix_node, NULL));
status = acpi_ns_evaluate(info);
acpi_ut_remove_reference(args[1]);
cleanup2:
acpi_ut_remove_reference(args[0]);
cleanup1:
ACPI_FREE(info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_methods
*
* PARAMETERS: node - Namespace node for the device
* space_id - The address space ID
*
* RETURN: Status
*
* DESCRIPTION: Run all _REG methods for the input Space ID;
* Note: assumes namespace is locked, or system init time.
*
******************************************************************************/
acpi_status
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
acpi_adr_space_type space_id)
{
acpi_status status;
struct acpi_reg_walk_info info;
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
info.space_id = space_id;
info.reg_run_count = 0;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
" Running _REG methods for SpaceId %s\n",
acpi_ut_get_region_name(info.space_id)));
/*
* Run all _REG methods for all Operation Regions for this space ID. This
* is a separate walk in order to handle any interdependencies between
* regions and _REG methods. (i.e. handlers must be installed for all
* regions of this Space ID before we can run any _REG methods)
*/
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
NULL, &info, NULL);
/* Special case for EC: handle "orphan" _REG methods with no region */
if (space_id == ACPI_ADR_SPACE_EC) {
acpi_ev_orphan_ec_reg_method(node);
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
" Executed %u _REG methods for SpaceId %s\n",
info.reg_run_count,
acpi_ut_get_region_name(info.space_id)));
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_reg_run
*
* PARAMETERS: walk_namespace callback
*
* DESCRIPTION: Run _REG method for region objects of the requested spaceID
*
******************************************************************************/
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
acpi_status status;
struct acpi_reg_walk_info *info;
info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);
/* Convert and validate the device handle */
node = acpi_ns_validate_handle(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
/*
* We only care about regions.and objects that are allowed to have address
* space handlers
*/
if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
return (AE_OK);
}
/* Object is a Region */
if (obj_desc->region.space_id != info->space_id) {
/* This region is for a different address space, just ignore it */
return (AE_OK);
}
info->reg_run_count++;
status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_orphan_ec_reg_method
*
* PARAMETERS: ec_device_node - Namespace node for an EC device
*
* RETURN: None
*
* DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
* device. This is a _REG method that has no corresponding region
* within the EC device scope. The orphan _REG method appears to
* have been enabled by the description of the ECDT in the ACPI
* specification: "The availability of the region space can be
* detected by providing a _REG method object underneath the
* Embedded Controller device."
*
* To quickly access the EC device, we use the ec_device_node used
* during EC handler installation. Otherwise, we would need to
* perform a time consuming namespace walk, executing _HID
* methods to find the EC device.
*
* MUTEX: Assumes the namespace is locked
*
******************************************************************************/
static void
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
{
acpi_handle reg_method;
struct acpi_namespace_node *next_node;
acpi_status status;
struct acpi_object_list args;
union acpi_object objects[2];
ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
if (!ec_device_node) {
return_VOID;
}
/* Namespace is currently locked, must release */
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* Get a handle to a _REG method immediately under the EC device */
status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, &reg_method);
if (ACPI_FAILURE(status)) {
goto exit; /* There is no _REG method present */
}
/*
* Execute the _REG method only if there is no Operation Region in
* this scope with the Embedded Controller space ID. Otherwise, it
* will already have been executed. Note, this allows for Regions
* with other space IDs to be present; but the code below will then
* execute the _REG method with the embedded_control space_ID argument.
*/
next_node = acpi_ns_get_next_node(ec_device_node, NULL);
while (next_node) {
if ((next_node->type == ACPI_TYPE_REGION) &&
(next_node->object) &&
(next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
goto exit; /* Do not execute the _REG */
}
next_node = acpi_ns_get_next_node(ec_device_node, next_node);
}
/* Evaluate the _REG(embedded_control,Connect) method */
args.count = 2;
args.pointer = objects;
objects[0].type = ACPI_TYPE_INTEGER;
objects[0].integer.value = ACPI_ADR_SPACE_EC;
objects[1].type = ACPI_TYPE_INTEGER;
objects[1].integer.value = ACPI_REG_CONNECT;
status = acpi_evaluate_object(reg_method, NULL, &args, NULL);
exit:
/* We ignore all errors from above, don't care */
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
return_VOID;
}

View File

@@ -1,675 +0,0 @@
/******************************************************************************
*
* Module Name: evrgnini- ACPI address_space (op_region) init
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evrgnini")
/* Local prototypes */
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
/*******************************************************************************
*
* FUNCTION: acpi_ev_system_memory_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Setup a system_memory operation region
*
******************************************************************************/
acpi_status
acpi_ev_system_memory_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
union acpi_operand_object *region_desc =
(union acpi_operand_object *)handle;
struct acpi_mem_space_context *local_region_context;
ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
if (*region_context) {
local_region_context =
(struct acpi_mem_space_context *)*region_context;
/* Delete a cached mapping if present */
if (local_region_context->mapped_length) {
acpi_os_unmap_memory(local_region_context->
mapped_logical_address,
local_region_context->
mapped_length);
}
ACPI_FREE(local_region_context);
*region_context = NULL;
}
return_ACPI_STATUS(AE_OK);
}
/* Create a new context */
local_region_context =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
if (!(local_region_context)) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the region length and address for use in the handler */
local_region_context->length = region_desc->region.length;
local_region_context->address = region_desc->region.address;
*region_context = local_region_context;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_io_space_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Setup a IO operation region
*
******************************************************************************/
acpi_status
acpi_ev_io_space_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
} else {
*region_context = handler_context;
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_config_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Setup a PCI_Config operation region
*
* MUTEX: Assumes namespace is not locked
*
******************************************************************************/
acpi_status
acpi_ev_pci_config_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
acpi_status status = AE_OK;
u64 pci_value;
struct acpi_pci_id *pci_id = *region_context;
union acpi_operand_object *handler_obj;
struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *pci_root_node;
struct acpi_namespace_node *pci_device_node;
union acpi_operand_object *region_obj =
(union acpi_operand_object *)handle;
ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
handler_obj = region_obj->region.handler;
if (!handler_obj) {
/*
* No installed handler. This shouldn't happen because the dispatch
* routine checks before we get here, but we check again just in case.
*/
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Attempting to init a region %p, with no handler\n",
region_obj));
return_ACPI_STATUS(AE_NOT_EXIST);
}
*region_context = NULL;
if (function == ACPI_REGION_DEACTIVATE) {
if (pci_id) {
ACPI_FREE(pci_id);
}
return_ACPI_STATUS(status);
}
parent_node = region_obj->region.node->parent;
/*
* Get the _SEG and _BBN values from the device upon which the handler
* is installed.
*
* We need to get the _SEG and _BBN objects relative to the PCI BUS device.
* This is the device the handler has been registered to handle.
*/
/*
* If the address_space.Node is still pointing to the root, we need
* to scan upward for a PCI Root bridge and re-associate the op_region
* handlers with that device.
*/
if (handler_obj->address_space.node == acpi_gbl_root_node) {
/* Start search from the parent object */
pci_root_node = parent_node;
while (pci_root_node != acpi_gbl_root_node) {
/* Get the _HID/_CID in order to detect a root_bridge */
if (acpi_ev_is_pci_root_bridge(pci_root_node)) {
/* Install a handler for this PCI root bridge */
status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
if (ACPI_FAILURE(status)) {
if (status == AE_SAME_HANDLER) {
/*
* It is OK if the handler is already installed on the
* root bridge. Still need to return a context object
* for the new PCI_Config operation region, however.
*/
status = AE_OK;
} else {
ACPI_EXCEPTION((AE_INFO, status,
"Could not install PciConfig handler "
"for Root Bridge %4.4s",
acpi_ut_get_node_name
(pci_root_node)));
}
}
break;
}
pci_root_node = pci_root_node->parent;
}
/* PCI root bridge not found, use namespace root node */
} else {
pci_root_node = handler_obj->address_space.node;
}
/*
* If this region is now initialized, we are done.
* (install_address_space_handler could have initialized it)
*/
if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
return_ACPI_STATUS(AE_OK);
}
/* Region is still not initialized. Create a new context */
pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
if (!pci_id) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* For PCI_Config space access, we need the segment, bus, device and
* function numbers. Acquire them here.
*
* Find the parent device object. (This allows the operation region to be
* within a subscope under the device, such as a control method.)
*/
pci_device_node = region_obj->region.node;
while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
pci_device_node = pci_device_node->parent;
}
if (!pci_device_node) {
ACPI_FREE(pci_id);
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* Get the PCI device and function numbers from the _ADR object
* contained in the parent's scope.
*/
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
pci_device_node, &pci_value);
/*
* The default is zero, and since the allocation above zeroed the data,
* just do nothing on failure.
*/
if (ACPI_SUCCESS(status)) {
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
}
/* The PCI segment number comes from the _SEG method */
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG,
pci_root_node, &pci_value);
if (ACPI_SUCCESS(status)) {
pci_id->segment = ACPI_LOWORD(pci_value);
}
/* The PCI bus number comes from the _BBN method */
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN,
pci_root_node, &pci_value);
if (ACPI_SUCCESS(status)) {
pci_id->bus = ACPI_LOWORD(pci_value);
}
/* Complete/update the PCI ID for this device */
status =
acpi_hw_derive_pci_id(pci_id, pci_root_node,
region_obj->region.node);
if (ACPI_FAILURE(status)) {
ACPI_FREE(pci_id);
return_ACPI_STATUS(status);
}
*region_context = pci_id;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_is_pci_root_bridge
*
* PARAMETERS: node - Device node being examined
*
* RETURN: TRUE if device is a PCI/PCI-Express Root Bridge
*
* DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
* examining the _HID and _CID for the device.
*
******************************************************************************/
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
{
acpi_status status;
struct acpi_pnp_device_id *hid;
struct acpi_pnp_device_id_list *cid;
u32 i;
u8 match;
/* Get the _HID and check for a PCI Root Bridge */
status = acpi_ut_execute_HID(node, &hid);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
match = acpi_ut_is_pci_root_bridge(hid->string);
ACPI_FREE(hid);
if (match) {
return (TRUE);
}
/* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
status = acpi_ut_execute_CID(node, &cid);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
/* Check all _CIDs in the returned list */
for (i = 0; i < cid->count; i++) {
if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
ACPI_FREE(cid);
return (TRUE);
}
}
ACPI_FREE(cid);
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_bar_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Setup a pci_BAR operation region
*
* MUTEX: Assumes namespace is not locked
*
******************************************************************************/
acpi_status
acpi_ev_pci_bar_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_cmos_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Setup a CMOS operation region
*
* MUTEX: Assumes namespace is not locked
*
******************************************************************************/
acpi_status
acpi_ev_cmos_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_default_region_setup
*
* PARAMETERS: handle - Region we are interested in
* function - Start or stop
* handler_context - Address space handler context
* region_context - Region specific context
*
* RETURN: Status
*
* DESCRIPTION: Default region initialization
*
******************************************************************************/
acpi_status
acpi_ev_default_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
ACPI_FUNCTION_TRACE(ev_default_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
} else {
*region_context = handler_context;
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_region
*
* PARAMETERS: region_obj - Region we are initializing
* acpi_ns_locked - Is namespace locked?
*
* RETURN: Status
*
* DESCRIPTION: Initializes the region, finds any _REG methods and saves them
* for execution at a later time
*
* Get the appropriate address space handler for a newly
* created region.
*
* This also performs address space specific initialization. For
* example, PCI regions must have an _ADR object that contains
* a PCI address in the scope of the definition. This address is
* required to perform an access to PCI config space.
*
* MUTEX: Interpreter should be unlocked, because we may run the _REG
* method for this region.
*
******************************************************************************/
acpi_status
acpi_ev_initialize_region(union acpi_operand_object *region_obj,
u8 acpi_ns_locked)
{
union acpi_operand_object *handler_obj;
union acpi_operand_object *obj_desc;
acpi_adr_space_type space_id;
struct acpi_namespace_node *node;
acpi_status status;
struct acpi_namespace_node *method_node;
acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
union acpi_operand_object *region_obj2;
ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
if (!region_obj) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
return_ACPI_STATUS(AE_OK);
}
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
node = region_obj->region.node->parent;
space_id = region_obj->region.space_id;
/* Setup defaults */
region_obj->region.handler = NULL;
region_obj2->extra.method_REG = NULL;
region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
/* Find any "_REG" method associated with this region definition */
status =
acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
&method_node);
if (ACPI_SUCCESS(status)) {
/*
* The _REG method is optional and there can be only one per region
* definition. This will be executed when the handler is attached
* or removed
*/
region_obj2->extra.method_REG = method_node;
}
/*
* The following loop depends upon the root Node having no parent
* ie: acpi_gbl_root_node->parent_entry being set to NULL
*/
while (node) {
/* Check to see if a handler exists */
handler_obj = NULL;
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* Can only be a handler if the object exists */
switch (node->type) {
case ACPI_TYPE_DEVICE:
handler_obj = obj_desc->device.handler;
break;
case ACPI_TYPE_PROCESSOR:
handler_obj = obj_desc->processor.handler;
break;
case ACPI_TYPE_THERMAL:
handler_obj = obj_desc->thermal_zone.handler;
break;
case ACPI_TYPE_METHOD:
/*
* If we are executing module level code, the original
* Node's object was replaced by this Method object and we
* saved the handler in the method object.
*
* See acpi_ns_exec_module_code
*/
if (obj_desc->method.
info_flags & ACPI_METHOD_MODULE_LEVEL) {
handler_obj =
obj_desc->method.dispatch.handler;
}
break;
default:
/* Ignore other objects */
break;
}
while (handler_obj) {
/* Is this handler of the correct type? */
if (handler_obj->address_space.space_id ==
space_id) {
/* Found correct handler */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Found handler %p for region %p in obj %p\n",
handler_obj,
region_obj,
obj_desc));
status =
acpi_ev_attach_region(handler_obj,
region_obj,
acpi_ns_locked);
/*
* Tell all users that this region is usable by
* running the _REG method
*/
if (acpi_ns_locked) {
status =
acpi_ut_release_mutex
(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS
(status);
}
}
status =
acpi_ev_execute_reg_method
(region_obj, ACPI_REG_CONNECT);
if (acpi_ns_locked) {
status =
acpi_ut_acquire_mutex
(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS
(status);
}
}
return_ACPI_STATUS(AE_OK);
}
/* Try next handler in the list */
handler_obj = handler_obj->address_space.next;
}
}
/* This node does not have the handler we need; Pop up one level */
node = node->parent;
}
/* If we get here, there is no handler for this region */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"No handler for RegionType %s(%X) (RegionObj %p)\n",
acpi_ut_get_region_name(space_id), space_id,
region_obj));
return_ACPI_STATUS(AE_NOT_EXIST);
}

View File

@@ -1,250 +0,0 @@
/*******************************************************************************
*
* Module Name: evsci - System Control Interrupt configuration and
* legacy to ACPI mode state transition functions
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evsci")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
/*******************************************************************************
*
* FUNCTION: acpi_ev_sci_dispatch
*
* PARAMETERS: None
*
* RETURN: Status code indicates whether interrupt was handled.
*
* DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
*
******************************************************************************/
u32 acpi_ev_sci_dispatch(void)
{
struct acpi_sci_handler_info *sci_handler;
acpi_cpu_flags flags;
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_NAME(ev_sci_dispatch);
/* Are there any host-installed SCI handlers? */
if (!acpi_gbl_sci_handler_list) {
return (int_status);
}
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Invoke all host-installed SCI handlers */
sci_handler = acpi_gbl_sci_handler_list;
while (sci_handler) {
/* Invoke the installed handler (at interrupt level) */
int_status |= sci_handler->address(sci_handler->context);
sci_handler = sci_handler->next;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return (int_status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_sci_xrupt_handler
*
* PARAMETERS: context - Calling Context
*
* RETURN: Status code indicates whether interrupt was handled.
*
* DESCRIPTION: Interrupt handler that will figure out what function or
* control method to call to deal with a SCI.
*
******************************************************************************/
static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
/*
* We are guaranteed by the ACPICA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
*/
/*
* Fixed Events:
* Check for and dispatch any Fixed Events that have occurred
*/
interrupt_handled |= acpi_ev_fixed_event_detect();
/*
* General Purpose Events:
* Check for and dispatch any GPEs that have occurred
*/
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
/* Invoke all host-installed SCI handlers */
interrupt_handled |= acpi_ev_sci_dispatch();
acpi_sci_count++;
return_UINT32(interrupt_handled);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_xrupt_handler
*
* PARAMETERS: context - Calling Context
*
* RETURN: Status code indicates whether interrupt was handled.
*
* DESCRIPTION: Handler for GPE Block Device interrupts
*
******************************************************************************/
u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
/*
* We are guaranteed by the ACPICA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
*/
/* GPEs: Check for and dispatch any GPEs that have occurred */
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
return_UINT32(interrupt_handled);
}
/******************************************************************************
*
* FUNCTION: acpi_ev_install_sci_handler
*
* PARAMETERS: none
*
* RETURN: Status
*
* DESCRIPTION: Installs SCI handler.
*
******************************************************************************/
u32 acpi_ev_install_sci_handler(void)
{
u32 status = AE_OK;
ACPI_FUNCTION_TRACE(ev_install_sci_handler);
status =
acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
acpi_ev_sci_xrupt_handler,
acpi_gbl_gpe_xrupt_list_head);
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_ev_remove_all_sci_handlers
*
* PARAMETERS: none
*
* RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not
* installed to begin with
*
* DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
* taken. Remove all host-installed SCI handlers.
*
* Note: It doesn't seem important to disable all events or set the event
* enable registers to their original values. The OS should disable
* the SCI interrupt level when the handler is removed, so no more
* events will come in.
*
******************************************************************************/
acpi_status acpi_ev_remove_all_sci_handlers(void)
{
struct acpi_sci_handler_info *sci_handler;
acpi_cpu_flags flags;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
/* Just let the OS remove the handler and disable the level */
status =
acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
acpi_ev_sci_xrupt_handler);
if (!acpi_gbl_sci_handler_list) {
return (status);
}
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Free all host-installed SCI handlers */
while (acpi_gbl_sci_handler_list) {
sci_handler = acpi_gbl_sci_handler_list;
acpi_gbl_sci_handler_list = sci_handler->next;
ACPI_FREE(sci_handler);
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

File diff suppressed because it is too large Load Diff

View File

@@ -1,381 +0,0 @@
/******************************************************************************
*
* Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#define EXPORT_ACPI_INTERFACES
#include <acpi/acpi.h>
#include "accommon.h"
#include "actables.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfevnt")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_enable
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Transfers the system into ACPI mode.
*
******************************************************************************/
acpi_status acpi_enable(void)
{
acpi_status status;
int retry;
ACPI_FUNCTION_TRACE(acpi_enable);
/* ACPI tables must be present */
if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
/* Check current mode */
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"System is already in ACPI mode\n"));
return_ACPI_STATUS(AE_OK);
}
/* Transition to ACPI mode */
status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not transition to ACPI mode"));
return_ACPI_STATUS(status);
}
/* Sanity check that transition succeeded */
for (retry = 0; retry < 30000; ++retry) {
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
if (retry != 0)
ACPI_WARNING((AE_INFO,
"Platform took > %d00 usec to enter ACPI mode", retry));
return_ACPI_STATUS(AE_OK);
}
acpi_os_stall(100); /* 100 usec */
}
ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
ACPI_EXPORT_SYMBOL(acpi_enable)
/*******************************************************************************
*
* FUNCTION: acpi_disable
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
*
******************************************************************************/
acpi_status acpi_disable(void)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(acpi_disable);
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"System is already in legacy (non-ACPI) mode\n"));
} else {
/* Transition to LEGACY mode */
status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not exit ACPI mode to legacy mode"));
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_disable)
/*******************************************************************************
*
* FUNCTION: acpi_enable_event
*
* PARAMETERS: event - The fixed eventto be enabled
* flags - Reserved
*
* RETURN: Status
*
* DESCRIPTION: Enable an ACPI event (fixed)
*
******************************************************************************/
acpi_status acpi_enable_event(u32 event, u32 flags)
{
acpi_status status = AE_OK;
u32 value;
ACPI_FUNCTION_TRACE(acpi_enable_event);
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Enable the requested fixed event (by writing a one to the enable
* register bit)
*/
status =
acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id, ACPI_ENABLE_EVENT);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Make sure that the hardware responded */
status =
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id, &value);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (value != 1) {
ACPI_ERROR((AE_INFO,
"Could not enable %s event",
acpi_ut_get_event_name(event)));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
*
* PARAMETERS: event - The fixed event to be disabled
* flags - Reserved
*
* RETURN: Status
*
* DESCRIPTION: Disable an ACPI event (fixed)
*
******************************************************************************/
acpi_status acpi_disable_event(u32 event, u32 flags)
{
acpi_status status = AE_OK;
u32 value;
ACPI_FUNCTION_TRACE(acpi_disable_event);
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Disable the requested fixed event (by writing a zero to the enable
* register bit)
*/
status =
acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id, ACPI_DISABLE_EVENT);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status =
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id, &value);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (value != 0) {
ACPI_ERROR((AE_INFO,
"Could not disable %s events",
acpi_ut_get_event_name(event)));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_disable_event)
/*******************************************************************************
*
* FUNCTION: acpi_clear_event
*
* PARAMETERS: event - The fixed event to be cleared
*
* RETURN: Status
*
* DESCRIPTION: Clear an ACPI event (fixed)
*
******************************************************************************/
acpi_status acpi_clear_event(u32 event)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(acpi_clear_event);
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Clear the requested fixed event (By writing a one to the status
* register bit)
*/
status =
acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
status_register_id, ACPI_CLEAR_STATUS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_clear_event)
/*******************************************************************************
*
* FUNCTION: acpi_get_event_status
*
* PARAMETERS: event - The fixed event
* event_status - Where the current status of the event will
* be returned
*
* RETURN: Status
*
* DESCRIPTION: Obtains and returns the current status of the event
*
******************************************************************************/
acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
{
acpi_status status;
acpi_event_status local_event_status = 0;
u32 in_byte;
ACPI_FUNCTION_TRACE(acpi_get_event_status);
if (!event_status) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Fixed event currently can be dispatched? */
if (acpi_gbl_fixed_event_handlers[event].handler) {
local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
}
/* Fixed event currently enabled? */
status =
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id, &in_byte);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (in_byte) {
local_event_status |=
(ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
}
/* Fixed event currently active? */
status =
acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
status_register_id, &in_byte);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (in_byte) {
local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
}
(*event_status) = local_event_status;
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_get_event_status)
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,952 +0,0 @@
/******************************************************************************
*
* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#define EXPORT_ACPI_INTERFACES
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_update_all_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Complete GPE initialization and enable all GPEs that have
* associated _Lxx or _Exx methods and are not pointed to by any
* device _PRW methods (this indicates that these GPEs are
* generally intended for system or device wakeup. Such GPEs
* have to be enabled directly when the devices whose _PRW
* methods point to them are set up for wakeup signaling.)
*
* NOTE: Should be called after any GPEs are added to the system. Primarily,
* after the system _PRW methods have been run, but also after a GPE Block
* Device has been added or if any new GPE methods have been added via a
* dynamic table load.
*
******************************************************************************/
acpi_status acpi_update_all_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (acpi_gbl_all_gpes_initialized) {
goto unlock_and_exit;
}
status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
if (ACPI_SUCCESS(status)) {
acpi_gbl_all_gpes_initialized = TRUE;
}
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
/*******************************************************************************
*
* FUNCTION: acpi_enable_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
* hardware-enabled.
*
******************************************************************************/
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_BAD_PARAMETER;
struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/*
* Ensure that we have a valid GPE number and that there is some way
* of handling the GPE (handler or a GPE method). In other words, we
* won't allow a valid GPE to be enabled if there is no way to handle it.
*/
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (gpe_event_info) {
if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
ACPI_GPE_DISPATCH_NONE) {
status = acpi_ev_add_gpe_reference(gpe_event_info);
} else {
status = AE_NO_HANDLER;
}
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
/*******************************************************************************
*
* FUNCTION: acpi_disable_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Remove a reference to a GPE. When the last reference is
* removed, only then is the GPE disabled (for runtime GPEs), or
* the GPE mask bit disabled (for wake GPEs)
*
******************************************************************************/
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_BAD_PARAMETER;
struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_disable_gpe);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (gpe_event_info) {
status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
/*******************************************************************************
*
* FUNCTION: acpi_set_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
* action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
*
* RETURN: Status
*
* DESCRIPTION: Enable or disable an individual GPE. This function bypasses
* the reference count mechanism used in the acpi_enable_gpe(),
* acpi_disable_gpe() interfaces.
* This API is typically used by the GPE raw handler mode driver
* to switch between the polling mode and the interrupt mode after
* the driver has enabled the GPE.
* The APIs should be invoked in this order:
* acpi_enable_gpe() <- Ensure the reference count > 0
* acpi_set_gpe(ACPI_GPE_DISABLE) <- Enter polling mode
* acpi_set_gpe(ACPI_GPE_ENABLE) <- Leave polling mode
* acpi_disable_gpe() <- Decrease the reference count
*
* Note: If a GPE is shared by 2 silicon components, then both the drivers
* should support GPE polling mode or disabling the GPE for long period
* for one driver may break the other. So use it with care since all
* firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
*
******************************************************************************/
acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
{
struct acpi_gpe_event_info *gpe_event_info;
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_set_gpe);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Perform the action */
switch (action) {
case ACPI_GPE_ENABLE:
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
break;
case ACPI_GPE_DISABLE:
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
break;
default:
status = AE_BAD_PARAMETER;
break;
}
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_set_gpe)
/*******************************************************************************
*
* FUNCTION: acpi_mark_gpe_for_wake
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
* sets the ACPI_GPE_CAN_WAKE flag.
*
* Some potential callers of acpi_setup_gpe_for_wake may know in advance that
* there won't be any notify handlers installed for device wake notifications
* from the given GPE (one example is a button GPE in Linux). For these cases,
* acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
* This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
* setup implicit wake notification for it (since there's no handler method).
*
******************************************************************************/
acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
{
struct acpi_gpe_event_info *gpe_event_info;
acpi_status status = AE_BAD_PARAMETER;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (gpe_event_info) {
/* Mark the GPE as a possible wake event */
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
status = AE_OK;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
/*******************************************************************************
*
* FUNCTION: acpi_setup_gpe_for_wake
*
* PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
* gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Mark a GPE as having the ability to wake the system. This
* interface is intended to be used as the host executes the
* _PRW methods (Power Resources for Wake) in the system tables.
* Each _PRW appears under a Device Object (The wake_device), and
* contains the info for the wake GPE associated with the
* wake_device.
*
******************************************************************************/
acpi_status
acpi_setup_gpe_for_wake(acpi_handle wake_device,
acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_namespace_node *device_node;
struct acpi_gpe_notify_info *notify;
struct acpi_gpe_notify_info *new_notify;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
/* Parameter Validation */
if (!wake_device) {
/*
* By forcing wake_device to be valid, we automatically enable the
* implicit notify feature on all hosts.
*/
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Handle root object case */
if (wake_device == ACPI_ROOT_OBJECT) {
device_node = acpi_gbl_root_node;
} else {
device_node =
ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
}
/* Validate wake_device is of type Device */
if (device_node->type != ACPI_TYPE_DEVICE) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/*
* Allocate a new notify object up front, in case it is needed.
* Memory allocation while holding a spinlock is a big no-no
* on some hosts.
*/
new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
if (!new_notify) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/*
* If there is no method or handler for this GPE, then the
* wake_device will be notified whenever this GPE fires. This is
* known as an "implicit notify". Note: The GPE is assumed to be
* level-triggered (for windows compatibility).
*/
if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_NONE) {
/*
* This is the first device for implicit notify on this GPE.
* Just set the flags here, and enter the NOTIFY block below.
*/
gpe_event_info->flags =
(ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
}
/*
* If we already have an implicit notify on this GPE, add
* this device to the notify list.
*/
if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
ACPI_GPE_DISPATCH_NOTIFY) {
/* Ensure that the device is not already in the list */
notify = gpe_event_info->dispatch.notify_list;
while (notify) {
if (notify->device_node == device_node) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
notify = notify->next;
}
/* Add this device to the notify list for this GPE */
new_notify->device_node = device_node;
new_notify->next = gpe_event_info->dispatch.notify_list;
gpe_event_info->dispatch.notify_list = new_notify;
new_notify = NULL;
}
/* Mark the GPE as a possible wake event */
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
status = AE_OK;
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Delete the notify object if it was not used above */
if (new_notify) {
ACPI_FREE(new_notify);
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
/*******************************************************************************
*
* FUNCTION: acpi_set_gpe_wake_mask
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
* action - Enable or Disable
*
* RETURN: Status
*
* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
* already be marked as a WAKE GPE.
*
******************************************************************************/
acpi_status
acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_gpe_register_info *gpe_register_info;
acpi_cpu_flags flags;
u32 register_bit;
ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/*
* Ensure that we have a valid GPE number and that this GPE is in
* fact a wake GPE
*/
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
status = AE_TYPE;
goto unlock_and_exit;
}
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* Perform the action */
switch (action) {
case ACPI_GPE_ENABLE:
ACPI_SET_BIT(gpe_register_info->enable_for_wake,
(u8)register_bit);
break;
case ACPI_GPE_DISABLE:
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
(u8)register_bit);
break;
default:
ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
status = AE_BAD_PARAMETER;
break;
}
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
/*******************************************************************************
*
* FUNCTION: acpi_clear_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Clear an ACPI event (general purpose)
*
******************************************************************************/
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_clear_gpe);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
status = acpi_hw_clear_gpe(gpe_event_info);
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_status
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
* event_status - Where the current status of the event
* will be returned
*
* RETURN: Status
*
* DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
*
******************************************************************************/
acpi_status
acpi_get_gpe_status(acpi_handle gpe_device,
u32 gpe_number, acpi_event_status *event_status)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Obtain status on the requested GPE number */
status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
/*******************************************************************************
*
* FUNCTION: acpi_finish_gpe
*
* PARAMETERS: gpe_device - Namespace node for the GPE Block
* (NULL for FADT defined GPEs)
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
* processing. Intended for use by asynchronous host-installed
* GPE handlers. The GPE is only reenabled if the enable_for_run bit
* is set in the GPE info.
*
******************************************************************************/
acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number)
{
struct acpi_gpe_event_info *gpe_event_info;
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_finish_gpe);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
status = acpi_ev_finish_gpe(gpe_event_info);
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_finish_gpe)
/******************************************************************************
*
* FUNCTION: acpi_disable_all_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks
*
******************************************************************************/
acpi_status acpi_disable_all_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_disable_all_gpes();
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
/******************************************************************************
*
* FUNCTION: acpi_enable_all_runtime_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
*
******************************************************************************/
acpi_status acpi_enable_all_runtime_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_enable_all_runtime_gpes();
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
/******************************************************************************
*
* FUNCTION: acpi_enable_all_wakeup_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
* all GPE blocks.
*
******************************************************************************/
acpi_status acpi_enable_all_wakeup_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_enable_all_wakeup_gpes();
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
/*******************************************************************************
*
* FUNCTION: acpi_install_gpe_block
*
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
* gpe_block_address - Address and space_ID
* register_count - Number of GPE register pairs in the block
* interrupt_number - H/W interrupt for the block
*
* RETURN: Status
*
* DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
* enabled here.
*
******************************************************************************/
acpi_status
acpi_install_gpe_block(acpi_handle gpe_device,
struct acpi_generic_address *gpe_block_address,
u32 register_count, u32 interrupt_number)
{
acpi_status status;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
node = acpi_ns_validate_handle(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Validate the parent device */
if (node->type != ACPI_TYPE_DEVICE) {
status = AE_TYPE;
goto unlock_and_exit;
}
if (node->object) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
/*
* For user-installed GPE Block Devices, the gpe_block_base_number
* is always zero
*/
status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
gpe_block_address->space_id,
register_count, 0, interrupt_number,
&gpe_block);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Install block in the device_object attached to the node */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/*
* No object, create a new one (Device nodes do not always have
* an attached object)
*/
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
status =
acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
/* Now install the GPE block in the device_object */
obj_desc->device.gpe_block = gpe_block;
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
/*******************************************************************************
*
* FUNCTION: acpi_remove_gpe_block
*
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
*
* RETURN: Status
*
* DESCRIPTION: Remove a previously installed block of GPE registers
*
******************************************************************************/
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
{
union acpi_operand_object *obj_desc;
acpi_status status;
struct acpi_namespace_node *node;
ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
if (!gpe_device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
node = acpi_ns_validate_handle(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Validate the parent device */
if (node->type != ACPI_TYPE_DEVICE) {
status = AE_TYPE;
goto unlock_and_exit;
}
/* Get the device_object attached to the node */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc || !obj_desc->device.gpe_block) {
return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Delete the GPE block (but not the device_object) */
status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
if (ACPI_SUCCESS(status)) {
obj_desc->device.gpe_block = NULL;
}
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_device
*
* PARAMETERS: index - System GPE index (0-current_gpe_count)
* gpe_device - Where the parent GPE Device is returned
*
* RETURN: Status
*
* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
* gpe device indicates that the gpe number is contained in one of
* the FADT-defined gpe blocks. Otherwise, the GPE block device.
*
******************************************************************************/
acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
{
struct acpi_gpe_device_info info;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
if (!gpe_device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (index >= acpi_current_gpe_count) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Setup and walk the GPE list */
info.index = index;
info.status = AE_NOT_EXIST;
info.gpe_device = NULL;
info.next_block_base_index = 0;
status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
return_ACPI_STATUS(info.status);
}
ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,295 +0,0 @@
/******************************************************************************
*
* Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
* Address Spaces.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#define EXPORT_ACPI_INTERFACES
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfregn")
/*******************************************************************************
*
* FUNCTION: acpi_install_address_space_handler
*
* PARAMETERS: device - Handle for the device
* space_id - The address space ID
* handler - Address of the handler
* setup - Address of the setup function
* context - Value passed to the handler on each access
*
* RETURN: Status
*
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
*
* NOTE: This function should only be called after acpi_enable_subsystem has
* been called. This is because any _REG methods associated with the Space ID
* are executed here, and these methods can only be safely executed after
* the default handlers have been installed and the hardware has been
* initialized (via acpi_enable_subsystem.)
*
******************************************************************************/
acpi_status
acpi_install_address_space_handler(acpi_handle device,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler,
acpi_adr_space_setup setup, void *context)
{
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
/* Parameter validation */
if (!device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
node = acpi_ns_validate_handle(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Install the handler for all Regions for this Space ID */
status =
acpi_ev_install_space_handler(node, space_id, handler, setup,
context);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/*
* For the default space_IDs, (the IDs for which there are default region handlers
* installed) Only execute the _REG methods if the global initialization _REG
* methods have already been run (via acpi_initialize_objects). In other words,
* we will defer the execution of the _REG methods for these space_IDs until
* execution of acpi_initialize_objects. This is done because we need the handlers
* for the default spaces (mem/io/pci/table) to be installed before we can run
* any control methods (or _REG methods). There is known BIOS code that depends
* on this.
*
* For all other space_IDs, we can safely execute the _REG methods immediately.
* This means that for IDs like embedded_controller, this function should be called
* only after acpi_enable_subsystem has been called.
*/
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
case ACPI_ADR_SPACE_SYSTEM_IO:
case ACPI_ADR_SPACE_PCI_CONFIG:
case ACPI_ADR_SPACE_DATA_TABLE:
if (!acpi_gbl_reg_methods_executed) {
/* We will defer execution of the _REG methods for this space */
goto unlock_and_exit;
}
break;
default:
break;
}
/* Run all _REG methods for this address space */
status = acpi_ev_execute_reg_methods(node, space_id);
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
/*******************************************************************************
*
* FUNCTION: acpi_remove_address_space_handler
*
* PARAMETERS: device - Handle for the device
* space_id - The address space ID
* handler - Address of the handler
*
* RETURN: Status
*
* DESCRIPTION: Remove a previously installed handler.
*
******************************************************************************/
acpi_status
acpi_remove_address_space_handler(acpi_handle device,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
union acpi_operand_object *region_obj;
union acpi_operand_object **last_obj_ptr;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
/* Parameter validation */
if (!device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
node = acpi_ns_validate_handle(device);
if (!node ||
((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
(node->type != ACPI_TYPE_THERMAL) &&
(node != acpi_gbl_root_node))) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure the internal object exists */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
/* Find the address handler the user requested */
handler_obj = obj_desc->device.handler;
last_obj_ptr = &obj_desc->device.handler;
while (handler_obj) {
/* We have a handler, see if user requested this one */
if (handler_obj->address_space.space_id == space_id) {
/* Handler must be the same as the installed handler */
if (handler_obj->address_space.handler != handler) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Matched space_id, first dereference this in the Regions */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Removing address handler %p(%p) for region %s "
"on Device %p(%p)\n",
handler_obj, handler,
acpi_ut_get_region_name(space_id),
node, obj_desc));
region_obj = handler_obj->address_space.region_list;
/* Walk the handler's region list */
while (region_obj) {
/*
* First disassociate the handler from the region.
*
* NOTE: this doesn't mean that the region goes away
* The region is just inaccessible as indicated to
* the _REG method
*/
acpi_ev_detach_region(region_obj, TRUE);
/*
* Walk the list: Just grab the head because the
* detach_region removed the previous head.
*/
region_obj =
handler_obj->address_space.region_list;
}
/* Remove this Handler object from the list */
*last_obj_ptr = handler_obj->address_space.next;
/* Now we can delete the handler object */
acpi_ut_remove_reference(handler_obj);
goto unlock_and_exit;
}
/* Walk the linked list of handlers */
last_obj_ptr = &handler_obj->address_space.next;
handler_obj = handler_obj->address_space.next;
}
/* The handler does not exist */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
handler, acpi_ut_get_region_name(space_id), space_id,
node, obj_desc));
status = AE_NOT_EXIST;
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)

View File

@@ -1,626 +0,0 @@
/******************************************************************************
*
* Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "actables.h"
#include "acdispat.h"
#include "acevents.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconfig")
/* Local prototypes */
static acpi_status
acpi_ex_add_table(u32 table_index,
struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle);
static acpi_status
acpi_ex_region_read(union acpi_operand_object *obj_desc,
u32 length, u8 *buffer);
/*******************************************************************************
*
* FUNCTION: acpi_ex_add_table
*
* PARAMETERS: table - Pointer to raw table
* parent_node - Where to load the table (scope)
* ddb_handle - Where to return the table handle.
*
* RETURN: Status
*
* DESCRIPTION: Common function to Install and Load an ACPI table with a
* returned table handle.
*
******************************************************************************/
static acpi_status
acpi_ex_add_table(u32 table_index,
struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle)
{
union acpi_operand_object *obj_desc;
acpi_status status;
acpi_owner_id owner_id;
ACPI_FUNCTION_TRACE(ex_add_table);
/* Create an object to be the table handle */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init the table handle */
obj_desc->common.flags |= AOPOBJ_DATA_VALID;
obj_desc->reference.class = ACPI_REFCLASS_TABLE;
*ddb_handle = obj_desc;
/* Install the new table into the local data structures */
obj_desc->reference.value = table_index;
/* Add the table to the namespace */
status = acpi_ns_load_table(table_index, parent_node);
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(obj_desc);
*ddb_handle = NULL;
return_ACPI_STATUS(status);
}
/* Execute any module-level code that was found in the table */
acpi_ex_exit_interpreter();
acpi_ns_exec_module_code_list();
acpi_ex_enter_interpreter();
/*
* Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
* responsible for discovering any new wake GPEs by running _PRW methods
* that may have been loaded by this table.
*/
status = acpi_tb_get_owner_id(table_index, &owner_id);
if (ACPI_SUCCESS(status)) {
acpi_ev_update_gpes(owner_id);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_table_op
*
* PARAMETERS: walk_state - Current state with operands
* return_desc - Where to store the return object
*
* RETURN: Status
*
* DESCRIPTION: Load an ACPI table from the RSDT/XSDT
*
******************************************************************************/
acpi_status
acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
union acpi_operand_object **return_desc)
{
acpi_status status;
union acpi_operand_object **operand = &walk_state->operands[0];
struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *start_node;
struct acpi_namespace_node *parameter_node = NULL;
union acpi_operand_object *ddb_handle;
struct acpi_table_header *table;
u32 table_index;
ACPI_FUNCTION_TRACE(ex_load_table_op);
/* Find the ACPI table in the RSDT/XSDT */
status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
return_ACPI_STATUS(status);
}
/* Table not found, return an Integer=0 and AE_OK */
ddb_handle = acpi_ut_create_integer_object((u64) 0);
if (!ddb_handle) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
*return_desc = ddb_handle;
return_ACPI_STATUS(AE_OK);
}
/* Default nodes */
start_node = walk_state->scope_info->scope.node;
parent_node = acpi_gbl_root_node;
/* root_path (optional parameter) */
if (operand[3]->string.length > 0) {
/*
* Find the node referenced by the root_path_string. This is the
* location within the namespace where the table will be loaded.
*/
status =
acpi_ns_get_node(start_node, operand[3]->string.pointer,
ACPI_NS_SEARCH_PARENT, &parent_node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* parameter_path (optional parameter) */
if (operand[4]->string.length > 0) {
if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) &&
(operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) {
/*
* Path is not absolute, so it will be relative to the node
* referenced by the root_path_string (or the NS root if omitted)
*/
start_node = parent_node;
}
/* Find the node referenced by the parameter_path_string */
status =
acpi_ns_get_node(start_node, operand[4]->string.pointer,
ACPI_NS_SEARCH_PARENT, &parameter_node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Load the table into the namespace */
status = acpi_ex_add_table(table_index, parent_node, &ddb_handle);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Parameter Data (optional) */
if (parameter_node) {
/* Store the parameter data into the optional parameter object */
status = acpi_ex_store(operand[5],
ACPI_CAST_PTR(union acpi_operand_object,
parameter_node),
walk_state);
if (ACPI_FAILURE(status)) {
(void)acpi_ex_unload_table(ddb_handle);
acpi_ut_remove_reference(ddb_handle);
return_ACPI_STATUS(status);
}
}
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) {
ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
acpi_tb_print_table_header(0, table);
}
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
acpi_gbl_table_handler_context);
}
*return_desc = ddb_handle;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_region_read
*
* PARAMETERS: obj_desc - Region descriptor
* length - Number of bytes to read
* buffer - Pointer to where to put the data
*
* RETURN: Status
*
* DESCRIPTION: Read data from an operation region. The read starts from the
* beginning of the region.
*
******************************************************************************/
static acpi_status
acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
{
acpi_status status;
u64 value;
u32 region_offset = 0;
u32 i;
/* Bytewise reads */
for (i = 0; i < length; i++) {
status =
acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
region_offset, 8, &value);
if (ACPI_FAILURE(status)) {
return (status);
}
*buffer = (u8)value;
buffer++;
region_offset++;
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_op
*
* PARAMETERS: obj_desc - Region or Buffer/Field where the table will be
* obtained
* target - Where a handle to the table will be stored
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Load an ACPI table from a field or operation region
*
* NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
* objects before this code is reached.
*
* If source is an operation region, it must refer to system_memory, as
* per the ACPI specification.
*
******************************************************************************/
acpi_status
acpi_ex_load_op(union acpi_operand_object *obj_desc,
union acpi_operand_object *target,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *ddb_handle;
struct acpi_table_header *table_header;
struct acpi_table_header *table;
u32 table_index;
acpi_status status;
u32 length;
ACPI_FUNCTION_TRACE(ex_load_op);
/* Source Object can be either an op_region or a Buffer/Field */
switch (obj_desc->common.type) {
case ACPI_TYPE_REGION:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Load table from Region %p\n", obj_desc));
/* Region must be system_memory (from ACPI spec) */
if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = acpi_ds_get_region_arguments(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Get the table header first so we can get the table length */
table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
if (!table_header) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
status =
acpi_ex_region_read(obj_desc,
sizeof(struct acpi_table_header),
ACPI_CAST_PTR(u8, table_header));
length = table_header->length;
ACPI_FREE(table_header);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Must have at least an ACPI table header */
if (length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/*
* The original implementation simply mapped the table, with no copy.
* However, the memory region is not guaranteed to remain stable and
* we must copy the table to a local buffer. For example, the memory
* region is corrupted after suspend on some machines. Dynamically
* loaded tables are usually small, so this overhead is minimal.
*
* The latest implementation (5/2009) does not use a mapping at all.
* We use the low-level operation region interface to read the table
* instead of the obvious optimization of using a direct mapping.
* This maintains a consistent use of operation regions across the
* entire subsystem. This is important if additional processing must
* be performed in the (possibly user-installed) operation region
* handler. For example, acpi_exec and ASLTS depend on this.
*/
/* Allocate a buffer for the table */
table = ACPI_ALLOCATE(length);
if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Read the entire table */
status = acpi_ex_region_read(obj_desc, length,
ACPI_CAST_PTR(u8, table));
if (ACPI_FAILURE(status)) {
ACPI_FREE(table);
return_ACPI_STATUS(status);
}
break;
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Load table from Buffer or Field %p\n",
obj_desc));
/* Must have at least an ACPI table header */
if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/* Get the actual table length from the table header */
table_header =
ACPI_CAST_PTR(struct acpi_table_header,
obj_desc->buffer.pointer);
length = table_header->length;
/* Table cannot extend beyond the buffer */
if (length > obj_desc->buffer.length) {
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
if (length < sizeof(struct acpi_table_header)) {
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/*
* Copy the table from the buffer because the buffer could be modified
* or even deleted in the future
*/
table = ACPI_ALLOCATE(length);
if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
memcpy(table, table_header, length);
break;
default:
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Install the new table into the local data structures */
ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
TRUE, TRUE, &table_index);
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
/* Delete allocated table buffer */
ACPI_FREE(table);
return_ACPI_STATUS(status);
}
/*
* Note: Now table is "INSTALLED", it must be validated before
* loading.
*/
status =
acpi_tb_validate_table(&acpi_gbl_root_table_list.
tables[table_index]);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Add the table to the namespace.
*
* Note: Load the table objects relative to the root of the namespace.
* This appears to go against the ACPI specification, but we do it for
* compatibility with other ACPI implementations.
*/
status =
acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
if (ACPI_FAILURE(status)) {
/* On error, table_ptr was deallocated above */
return_ACPI_STATUS(status);
}
/* Store the ddb_handle into the Target operand */
status = acpi_ex_store(ddb_handle, target, walk_state);
if (ACPI_FAILURE(status)) {
(void)acpi_ex_unload_table(ddb_handle);
/* table_ptr was deallocated above */
acpi_ut_remove_reference(ddb_handle);
return_ACPI_STATUS(status);
}
/* Remove the reference by added by acpi_ex_store above */
acpi_ut_remove_reference(ddb_handle);
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
acpi_gbl_table_handler_context);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_unload_table
*
* PARAMETERS: ddb_handle - Handle to a previously loaded table
*
* RETURN: Status
*
* DESCRIPTION: Unload an ACPI table
*
******************************************************************************/
acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
{
acpi_status status = AE_OK;
union acpi_operand_object *table_desc = ddb_handle;
u32 table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_unload_table);
/*
* Temporarily emit a warning so that the ASL for the machine can be
* hopefully obtained. This is to say that the Unload() operator is
* extremely rare if not completely unused.
*/
ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
/*
* Validate the handle
* Although the handle is partially validated in acpi_ex_reconfiguration()
* when it calls acpi_ex_resolve_operands(), the handle is more completely
* validated here.
*
* Handle must be a valid operand object of type reference. Also, the
* ddb_handle must still be marked valid (table has not been previously
* unloaded)
*/
if ((!ddb_handle) ||
(ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
(ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
(!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Get the table index from the ddb_handle */
table_index = table_desc->reference.value;
/* Ensure the table is still loaded */
if (!acpi_tb_is_table_loaded(table_index)) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
table,
acpi_gbl_table_handler_context);
}
}
/* Delete the portion of the namespace owned by this table */
status = acpi_tb_delete_namespace_by_owner(table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
(void)acpi_tb_release_owner_id(table_index);
acpi_tb_set_table_loaded_flag(table_index, FALSE);
/*
* Invalidate the handle. We do this because the handle may be stored
* in a named object and may not be actually deleted until much later.
*/
ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,694 +0,0 @@
/******************************************************************************
*
* Module Name: exconvrt - Object conversion routines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconvrt")
/* Local prototypes */
static u32
acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length);
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_integer
*
* PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new Integer object is returned
* flags - Used for string conversion
*
* RETURN: Status
*
* DESCRIPTION: Convert an ACPI Object to an integer.
*
******************************************************************************/
acpi_status
acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc, u32 flags)
{
union acpi_operand_object *return_desc;
u8 *pointer;
u64 result;
u32 i;
u32 count;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
/* No conversion necessary */
*result_desc = obj_desc;
return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
/* Note: Takes advantage of common buffer/string fields */
pointer = obj_desc->buffer.pointer;
count = obj_desc->buffer.length;
break;
default:
return_ACPI_STATUS(AE_TYPE);
}
/*
* Convert the buffer/string to an integer. Note that both buffers and
* strings are treated as raw data - we don't convert ascii to hex for
* strings.
*
* There are two terminating conditions for the loop:
* 1) The size of an integer has been reached, or
* 2) The end of the buffer or string has been reached
*/
result = 0;
/* String conversion is different than Buffer conversion */
switch (obj_desc->common.type) {
case ACPI_TYPE_STRING:
/*
* Convert string to an integer - for most cases, the string must be
* hexadecimal as per the ACPI specification. The only exception (as
* of ACPI 3.0) is that the to_integer() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
status = acpi_ut_strtoul64((char *)pointer, flags, &result);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
break;
case ACPI_TYPE_BUFFER:
/* Check for zero-length buffer */
if (!count) {
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
/* Transfer no more than an integer's worth of data */
if (count > acpi_gbl_integer_byte_width) {
count = acpi_gbl_integer_byte_width;
}
/*
* Convert buffer to an integer - we simply grab enough raw data
* from the buffer to fill an integer
*/
for (i = 0; i < count; i++) {
/*
* Get next byte and shift it into the Result.
* Little endian is used, meaning that the first byte of the buffer
* is the LSB of the integer
*/
result |= (((u64) pointer[i]) << (i * 8));
}
break;
default:
/* No other types can get here */
break;
}
/* Create a new integer */
return_desc = acpi_ut_create_integer_object(result);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(result)));
/* Save the Result */
(void)acpi_ex_truncate_for32bit_table(return_desc);
*result_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_buffer
*
* PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new buffer object is returned
*
* RETURN: Status
*
* DESCRIPTION: Convert an ACPI Object to a Buffer
*
******************************************************************************/
acpi_status
acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc)
{
union acpi_operand_object *return_desc;
u8 *new_buf;
ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
switch (obj_desc->common.type) {
case ACPI_TYPE_BUFFER:
/* No conversion necessary */
*result_desc = obj_desc;
return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
/*
* Create a new Buffer object.
* Need enough space for one integer
*/
return_desc =
acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the integer to the buffer, LSB first */
new_buf = return_desc->buffer.pointer;
memcpy(new_buf,
&obj_desc->integer.value, acpi_gbl_integer_byte_width);
break;
case ACPI_TYPE_STRING:
/*
* Create a new Buffer object
* Size will be the string length
*
* NOTE: Add one to the string length to include the null terminator.
* The ACPI spec is unclear on this subject, but there is existing
* ASL/AML code that depends on the null being transferred to the new
* buffer.
*/
return_desc = acpi_ut_create_buffer_object((acpi_size)
obj_desc->string.
length + 1);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the string to the buffer */
new_buf = return_desc->buffer.pointer;
strncpy((char *)new_buf, (char *)obj_desc->string.pointer,
obj_desc->string.length);
break;
default:
return_ACPI_STATUS(AE_TYPE);
}
/* Mark buffer initialized */
return_desc->common.flags |= AOPOBJ_DATA_VALID;
*result_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_ascii
*
* PARAMETERS: integer - Value to be converted
* base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
* string - Where the string is returned
* data_width - Size of data item to be converted, in bytes
*
* RETURN: Actual string length
*
* DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
*
******************************************************************************/
static u32
acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width)
{
u64 digit;
u32 i;
u32 j;
u32 k = 0;
u32 hex_length;
u32 decimal_length;
u32 remainder;
u8 supress_zeros;
ACPI_FUNCTION_ENTRY();
switch (base) {
case 10:
/* Setup max length for the decimal number */
switch (data_width) {
case 1:
decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
break;
case 4:
decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
break;
case 8:
default:
decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
break;
}
supress_zeros = TRUE; /* No leading zeros */
remainder = 0;
for (i = decimal_length; i > 0; i--) {
/* Divide by nth factor of 10 */
digit = integer;
for (j = 0; j < i; j++) {
(void)acpi_ut_short_divide(digit, 10, &digit,
&remainder);
}
/* Handle leading zeros */
if (remainder != 0) {
supress_zeros = FALSE;
}
if (!supress_zeros) {
string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
k++;
}
}
break;
case 16:
/* hex_length: 2 ascii hex chars per data byte */
hex_length = ACPI_MUL_2(data_width);
for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
/* Get one hex digit, most significant digits first */
string[k] =
(u8) acpi_ut_hex_to_ascii_char(integer,
ACPI_MUL_4(j));
k++;
}
break;
default:
return (0);
}
/*
* Since leading zeros are suppressed, we must check for the case where
* the integer equals 0
*
* Finally, null terminate the string and return the length
*/
if (!k) {
string[0] = ACPI_ASCII_ZERO;
k = 1;
}
string[k] = 0;
return ((u32) k);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_string
*
* PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the string object is returned
* type - String flags (base and conversion type)
*
* RETURN: Status
*
* DESCRIPTION: Convert an ACPI Object to a string
*
******************************************************************************/
acpi_status
acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
union acpi_operand_object ** result_desc, u32 type)
{
union acpi_operand_object *return_desc;
u8 *new_buf;
u32 i;
u32 string_length = 0;
u16 base = 16;
u8 separator = ',';
ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
switch (obj_desc->common.type) {
case ACPI_TYPE_STRING:
/* No conversion necessary */
*result_desc = obj_desc;
return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
switch (type) {
case ACPI_EXPLICIT_CONVERT_DECIMAL:
/* Make room for maximum decimal number */
string_length = ACPI_MAX_DECIMAL_DIGITS;
base = 10;
break;
default:
/* Two hex string characters for each integer byte */
string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
break;
}
/*
* Create a new String
* Need enough space for one ASCII integer (plus null terminator)
*/
return_desc =
acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
/* Convert integer to string */
string_length =
acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
new_buf,
acpi_gbl_integer_byte_width);
/* Null terminate at the correct place */
return_desc->string.length = string_length;
new_buf[string_length] = 0;
break;
case ACPI_TYPE_BUFFER:
/* Setup string length, base, and separator */
switch (type) {
case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* decimal values separated by commas."
*/
base = 10;
/*
* Calculate the final string length. Individual string values
* are variable length (include separator for each)
*/
for (i = 0; i < obj_desc->buffer.length; i++) {
if (obj_desc->buffer.pointer[i] >= 100) {
string_length += 4;
} else if (obj_desc->buffer.pointer[i] >= 10) {
string_length += 3;
} else {
string_length += 2;
}
}
break;
case ACPI_IMPLICIT_CONVERT_HEX:
/*
* From the ACPI spec:
*"The entire contents of the buffer are converted to a string of
* two-character hexadecimal numbers, each separated by a space."
*/
separator = ' ';
string_length = (obj_desc->buffer.length * 3);
break;
case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* hexadecimal values separated by commas."
*/
string_length = (obj_desc->buffer.length * 3);
break;
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Create a new string object and string buffer
* (-1 because of extra separator included in string_length from above)
* Allow creation of zero-length strings from zero-length buffers.
*/
if (string_length) {
string_length--;
}
return_desc =
acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
/*
* Convert buffer bytes to hex or decimal values
* (separated by commas or spaces)
*/
for (i = 0; i < obj_desc->buffer.length; i++) {
new_buf += acpi_ex_convert_to_ascii((u64) obj_desc->
buffer.pointer[i],
base, new_buf, 1);
*new_buf++ = separator; /* each separated by a comma or space */
}
/*
* Null terminate the string
* (overwrites final comma/space from above)
*/
if (obj_desc->buffer.length) {
new_buf--;
}
*new_buf = 0;
break;
default:
return_ACPI_STATUS(AE_TYPE);
}
*result_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_target_type
*
* PARAMETERS: destination_type - Current type of the destination
* source_desc - Source object to be converted.
* result_desc - Where the converted object is returned
* walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Implements "implicit conversion" rules for storing an object.
*
******************************************************************************/
acpi_status
acpi_ex_convert_to_target_type(acpi_object_type destination_type,
union acpi_operand_object *source_desc,
union acpi_operand_object **result_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
/* Default behavior */
*result_desc = source_desc;
/*
* If required by the target,
* perform implicit conversion on the source before we store it.
*/
switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
case ARGI_SIMPLE_TARGET:
case ARGI_FIXED_TARGET:
case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
switch (destination_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
/*
* Named field can always handle conversions
*/
break;
default:
/* No conversion allowed for these types */
if (destination_type != source_desc->common.type) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Explicit operator, will store (%s) over existing type (%s)\n",
acpi_ut_get_object_type_name
(source_desc),
acpi_ut_get_type_name
(destination_type)));
status = AE_TYPE;
}
}
break;
case ARGI_TARGETREF:
case ARGI_STORE_TARGET:
switch (destination_type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/*
* These types require an Integer operand. We can convert
* a Buffer or a String to an Integer if necessary.
*/
status =
acpi_ex_convert_to_integer(source_desc, result_desc,
16);
break;
case ACPI_TYPE_STRING:
/*
* The operand must be a String. We can convert an
* Integer or Buffer if necessary
*/
status =
acpi_ex_convert_to_string(source_desc, result_desc,
ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
/*
* The operand must be a Buffer. We can convert an
* Integer or String if necessary
*/
status =
acpi_ex_convert_to_buffer(source_desc, result_desc);
break;
default:
ACPI_ERROR((AE_INFO,
"Bad destination type during conversion: 0x%X",
destination_type));
status = AE_AML_INTERNAL;
break;
}
break;
case ARGI_REFERENCE:
/*
* create_xxxx_field cases - we are storing the field object into the name
*/
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
GET_CURRENT_ARG_TYPE(walk_state->op_info->
runtime_args),
walk_state->opcode,
acpi_ut_get_type_name(destination_type)));
status = AE_AML_INTERNAL;
}
/*
* Source-to-Target conversion semantics:
*
* If conversion to the target type cannot be performed, then simply
* overwrite the target with the new object and type.
*/
if (status == AE_TYPE) {
status = AE_OK;
}
return_ACPI_STATUS(status);
}

View File

@@ -1,529 +0,0 @@
/******************************************************************************
*
* Module Name: excreate - Named object creation
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("excreate")
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_alias
*
* PARAMETERS: walk_state - Current state, contains operands
*
* RETURN: Status
*
* DESCRIPTION: Create a new named alias
*
******************************************************************************/
acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
{
struct acpi_namespace_node *target_node;
struct acpi_namespace_node *alias_node;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_create_alias);
/* Get the source/alias operands (both namespace nodes) */
alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
target_node = (struct acpi_namespace_node *)walk_state->operands[1];
if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
(target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/*
* Dereference an existing alias so that we don't create a chain
* of aliases. With this code, we guarantee that an alias is
* always exactly one level of indirection away from the
* actual aliased name.
*/
target_node =
ACPI_CAST_PTR(struct acpi_namespace_node,
target_node->object);
}
/*
* For objects that can never change (i.e., the NS node will
* permanently point to the same object), we can simply attach
* the object to the new NS node. For other objects (such as
* Integers, buffers, etc.), we have to point the Alias node
* to the original Node.
*/
switch (target_node->type) {
/* For these types, the sub-object can change dynamically via a Store */
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_BUFFER_FIELD:
/*
* These types open a new scope, so we need the NS node in order to access
* any children.
*/
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
case ACPI_TYPE_LOCAL_SCOPE:
/*
* The new alias has the type ALIAS and points to the original
* NS node, not the object itself.
*/
alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
alias_node->object =
ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
case ACPI_TYPE_METHOD:
/*
* Control method aliases need to be differentiated
*/
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
alias_node->object =
ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
default:
/* Attach the original source object to the new Alias Node */
/*
* The new alias assumes the type of the target, and it points
* to the same object. The reference count of the object has an
* additional reference to prevent deletion out from under either the
* target node or the alias Node
*/
status = acpi_ns_attach_object(alias_node,
acpi_ns_get_attached_object
(target_node),
target_node->type);
break;
}
/* Since both operands are Nodes, we don't need to delete them */
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_event
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new event object
*
******************************************************************************/
acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_TRACE(ex_create_event);
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* Create the actual OS semaphore, with zero initial units -- meaning
* that the event is created in an unsignalled state
*/
status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
&obj_desc->event.os_semaphore);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Attach object to the Node */
status =
acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
operands[0], obj_desc, ACPI_TYPE_EVENT);
cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_mutex
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new mutex object
*
* Mutex (Name[0], sync_level[1])
*
******************************************************************************/
acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
/* Create the new mutex object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Create the actual OS Mutex */
status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Init object and attach to NS node */
obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
obj_desc->mutex.node =
(struct acpi_namespace_node *)walk_state->operands[0];
status =
acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
ACPI_TYPE_MUTEX);
cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_region
*
* PARAMETERS: aml_start - Pointer to the region declaration AML
* aml_length - Max length of the declaration AML
* space_id - Address space ID for the region
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new operation region object
*
******************************************************************************/
acpi_status
acpi_ex_create_region(u8 * aml_start,
u32 aml_length,
u8 space_id, struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
union acpi_operand_object *region_obj2;
ACPI_FUNCTION_TRACE(ex_create_region);
/* Get the Namespace Node */
node = walk_state->op->common.node;
/*
* If the region object is already attached to this node,
* just return
*/
if (acpi_ns_get_attached_object(node)) {
return_ACPI_STATUS(AE_OK);
}
/*
* Space ID must be one of the predefined IDs, or in the user-defined
* range
*/
if (!acpi_is_valid_space_id(space_id)) {
/*
* Print an error message, but continue. We don't want to abort
* a table load for this exception. Instead, if the region is
* actually used at runtime, abort the executing method.
*/
ACPI_ERROR((AE_INFO,
"Invalid/unknown Address Space ID: 0x%2.2X",
space_id));
}
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
acpi_ut_get_region_name(space_id), space_id));
/* Create the region descriptor */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* Remember location in AML stream of address & length
* operands since they need to be evaluated at run time.
*/
region_obj2 = obj_desc->common.next_object;
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
if (walk_state->scope_info) {
region_obj2->extra.scope_node =
walk_state->scope_info->scope.node;
} else {
region_obj2->extra.scope_node = node;
}
/* Init the region from the operands */
obj_desc->region.space_id = space_id;
obj_desc->region.address = 0;
obj_desc->region.length = 0;
obj_desc->region.node = node;
/* Install the new region object in the parent Node */
status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
cleanup:
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_processor
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new processor object and populate the fields
*
* Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3])
*
******************************************************************************/
acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *obj_desc;
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
/* Create the processor object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the processor object from the operands */
obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
obj_desc->processor.length = (u8) operand[3]->integer.value;
obj_desc->processor.address =
(acpi_io_address) operand[2]->integer.value;
/* Install the processor object in the parent Node */
status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
obj_desc, ACPI_TYPE_PROCESSOR);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_power_resource
*
* PARAMETERS: walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new power_resource object and populate the fields
*
* power_resource (Name[0], system_level[1], resource_order[2])
*
******************************************************************************/
acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
acpi_status status;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
/* Create the power resource object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the power object from the operands */
obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
obj_desc->power_resource.resource_order =
(u16) operand[2]->integer.value;
/* Install the power resource object in the parent Node */
status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
obj_desc, ACPI_TYPE_POWER);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_method
*
* PARAMETERS: aml_start - First byte of the method's AML
* aml_length - AML byte count for this method
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Create a new method object
*
******************************************************************************/
acpi_status
acpi_ex_create_method(u8 * aml_start,
u32 aml_length, struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *obj_desc;
acpi_status status;
u8 method_flags;
ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
/* Create a new method object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto exit;
}
/* Save the method's AML pointer and length */
obj_desc->method.aml_start = aml_start;
obj_desc->method.aml_length = aml_length;
obj_desc->method.node = operand[0];
/*
* Disassemble the method flags. Split off the arg_count, Serialized
* flag, and sync_level for efficiency.
*/
method_flags = (u8) operand[1]->integer.value;
obj_desc->method.param_count =
(u8) (method_flags & AML_METHOD_ARG_COUNT);
/*
* Get the sync_level. If method is serialized, a mutex will be
* created for this method when it is parsed.
*/
if (method_flags & AML_METHOD_SERIALIZED) {
obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
/*
* ACPI 1.0: sync_level = 0
* ACPI 2.0: sync_level = sync_level in method declaration
*/
obj_desc->method.sync_level = (u8)
((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
}
/* Attach the new object to the method Node */
status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
obj_desc, ACPI_TYPE_METHOD);
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
exit:
/* Remove a reference to the operand */
acpi_ut_remove_reference(operand[1]);
return_ACPI_STATUS(status);
}

View File

@@ -1,634 +0,0 @@
/******************************************************************************
*
* Module Name: exdebug - Support for stores to the AML Debug Object
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acinterp.h"
#include "acparser.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exdebug")
static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
/* Local prototypes */
#ifdef ACPI_DEBUG_OUTPUT
static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
#endif
#ifndef ACPI_NO_ERROR_MESSAGES
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_debug_object
*
* PARAMETERS: source_desc - Object to be output to "Debug Object"
* level - Indentation level (used for packages)
* index - Current package element, zero if not pkg
*
* RETURN: None
*
* DESCRIPTION: Handles stores to the AML Debug Object. For example:
* Store(INT1, Debug)
*
* This function is not compiled if ACPI_NO_ERROR_MESSAGES is set.
*
* This function is only enabled if acpi_gbl_enable_aml_debug_object is set, or
* if ACPI_LV_DEBUG_OBJECT is set in the acpi_dbg_level. Thus, in the normal
* operational case, stores to the debug object are ignored but can be easily
* enabled if necessary.
*
******************************************************************************/
void
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
u32 level, u32 index)
{
u32 i;
u32 timer;
union acpi_operand_object *object_desc;
u32 value;
ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
/* Output must be enabled via the debug_object global or the dbg_level */
if (!acpi_gbl_enable_aml_debug_object &&
!(acpi_dbg_level & ACPI_LV_DEBUG_OBJECT)) {
return_VOID;
}
/*
* We will emit the current timer value (in microseconds) with each
* debug output. Only need the lower 26 bits. This allows for 67
* million microseconds or 67 seconds before rollover.
*/
timer = ((u32)acpi_os_get_timer() / 10); /* (100 nanoseconds to microseconds) */
timer &= 0x03FFFFFF;
/*
* Print line header as long as we are not in the middle of an
* object display
*/
if (!((level > 0) && index == 0)) {
acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " ");
}
/* Display the index for package output only */
if (index > 0) {
acpi_os_printf("(%.2u) ", index - 1);
}
if (!source_desc) {
acpi_os_printf("[Null Object]\n");
return_VOID;
}
if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf("%s ",
acpi_ut_get_object_type_name(source_desc));
if (!acpi_ut_valid_internal_object(source_desc)) {
acpi_os_printf("%p, Invalid Internal Object!\n",
source_desc);
return_VOID;
}
} else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
ACPI_DESC_TYPE_NAMED) {
acpi_os_printf("%s: %p\n",
acpi_ut_get_type_name(((struct
acpi_namespace_node *)
source_desc)->type),
source_desc);
return_VOID;
} else {
return_VOID;
}
/* source_desc is of type ACPI_DESC_TYPE_OPERAND */
switch (source_desc->common.type) {
case ACPI_TYPE_INTEGER:
/* Output correct integer width */
if (acpi_gbl_integer_byte_width == 4) {
acpi_os_printf("0x%8.8X\n",
(u32)source_desc->integer.value);
} else {
acpi_os_printf("0x%8.8X%8.8X\n",
ACPI_FORMAT_UINT64(source_desc->integer.
value));
}
break;
case ACPI_TYPE_BUFFER:
acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length);
acpi_ut_dump_buffer(source_desc->buffer.pointer,
(source_desc->buffer.length < 256) ?
source_desc->buffer.length : 256,
DB_BYTE_DISPLAY, 0);
break;
case ACPI_TYPE_STRING:
acpi_os_printf("[0x%.2X] \"%s\"\n",
source_desc->string.length,
source_desc->string.pointer);
break;
case ACPI_TYPE_PACKAGE:
acpi_os_printf("[Contains 0x%.2X Elements]\n",
source_desc->package.count);
/* Output the entire contents of the package */
for (i = 0; i < source_desc->package.count; i++) {
acpi_ex_do_debug_object(source_desc->package.
elements[i], level + 4, i + 1);
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[%s] ",
acpi_ut_get_reference_name(source_desc));
/* Decode the reference */
switch (source_desc->reference.class) {
case ACPI_REFCLASS_INDEX:
acpi_os_printf("0x%X\n", source_desc->reference.value);
break;
case ACPI_REFCLASS_TABLE:
/* Case for ddb_handle */
acpi_os_printf("Table Index 0x%X\n",
source_desc->reference.value);
return_VOID;
default:
break;
}
acpi_os_printf(" ");
/* Check for valid node first, then valid object */
if (source_desc->reference.node) {
if (ACPI_GET_DESCRIPTOR_TYPE
(source_desc->reference.node) !=
ACPI_DESC_TYPE_NAMED) {
acpi_os_printf
(" %p - Not a valid namespace node\n",
source_desc->reference.node);
} else {
acpi_os_printf("Node %p [%4.4s] ",
source_desc->reference.node,
(source_desc->reference.node)->
name.ascii);
switch ((source_desc->reference.node)->type) {
/* These types have no attached object */
case ACPI_TYPE_DEVICE:
acpi_os_printf("Device\n");
break;
case ACPI_TYPE_THERMAL:
acpi_os_printf("Thermal Zone\n");
break;
default:
acpi_ex_do_debug_object((source_desc->
reference.
node)->object,
level + 4, 0);
break;
}
}
} else if (source_desc->reference.object) {
if (ACPI_GET_DESCRIPTOR_TYPE
(source_desc->reference.object) ==
ACPI_DESC_TYPE_NAMED) {
acpi_ex_do_debug_object(((struct
acpi_namespace_node *)
source_desc->reference.
object)->object,
level + 4, 0);
} else {
object_desc = source_desc->reference.object;
value = source_desc->reference.value;
switch (object_desc->common.type) {
case ACPI_TYPE_BUFFER:
acpi_os_printf("Buffer[%u] = 0x%2.2X\n",
value,
*source_desc->reference.
index_pointer);
break;
case ACPI_TYPE_STRING:
acpi_os_printf
("String[%u] = \"%c\" (0x%2.2X)\n",
value,
*source_desc->reference.
index_pointer,
*source_desc->reference.
index_pointer);
break;
case ACPI_TYPE_PACKAGE:
acpi_os_printf("Package[%u] = ", value);
acpi_ex_do_debug_object(*source_desc->
reference.where,
level + 4, 0);
break;
default:
acpi_os_printf
("Unknown Reference object type %X\n",
object_desc->common.type);
break;
}
}
}
break;
default:
acpi_os_printf("%p\n", source_desc);
break;
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n"));
return_VOID;
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ex_interpreter_trace_enabled
*
* PARAMETERS: name - Whether method name should be matched,
* this should be checked before starting
* the tracer
*
* RETURN: TRUE if interpreter trace is enabled.
*
* DESCRIPTION: Check whether interpreter trace is enabled
*
******************************************************************************/
static u8 acpi_ex_interpreter_trace_enabled(char *name)
{
/* Check if tracing is enabled */
if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
return (FALSE);
}
/*
* Check if tracing is filtered:
*
* 1. If the tracer is started, acpi_gbl_trace_method_object should have
* been filled by the trace starter
* 2. If the tracer is not started, acpi_gbl_trace_method_name should be
* matched if it is specified
* 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
* not be cleared by the trace stopper during the first match
*/
if (acpi_gbl_trace_method_object) {
return (TRUE);
}
if (name &&
(acpi_gbl_trace_method_name &&
strcmp(acpi_gbl_trace_method_name, name))) {
return (FALSE);
}
if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
!acpi_gbl_trace_method_name) {
return (FALSE);
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_trace_event_name
*
* PARAMETERS: type - Trace event type
*
* RETURN: Trace event name.
*
* DESCRIPTION: Used to obtain the full trace event name.
*
******************************************************************************/
#ifdef ACPI_DEBUG_OUTPUT
static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
{
switch (type) {
case ACPI_TRACE_AML_METHOD:
return "Method";
case ACPI_TRACE_AML_OPCODE:
return "Opcode";
case ACPI_TRACE_AML_REGION:
return "Region";
default:
return "";
}
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ex_trace_point
*
* PARAMETERS: type - Trace event type
* begin - TRUE if before execution
* aml - Executed AML address
* pathname - Object path
*
* RETURN: None
*
* DESCRIPTION: Internal interpreter execution trace.
*
******************************************************************************/
void
acpi_ex_trace_point(acpi_trace_event_type type,
u8 begin, u8 *aml, char *pathname)
{
ACPI_FUNCTION_NAME(ex_trace_point);
if (pathname) {
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
"%s %s [0x%p:%s] execution.\n",
acpi_ex_get_trace_event_name(type),
begin ? "Begin" : "End", aml, pathname));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
"%s %s [0x%p] execution.\n",
acpi_ex_get_trace_event_name(type),
begin ? "Begin" : "End", aml));
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_start_trace_method
*
* PARAMETERS: method_node - Node of the method
* obj_desc - The method object
* walk_state - current state, NULL if not yet executing
* a method.
*
* RETURN: None
*
* DESCRIPTION: Start control method execution trace
*
******************************************************************************/
void
acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
char *pathname = NULL;
u8 enabled = FALSE;
ACPI_FUNCTION_NAME(ex_start_trace_method);
if (method_node) {
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
}
enabled = acpi_ex_interpreter_trace_enabled(pathname);
if (enabled && !acpi_gbl_trace_method_object) {
acpi_gbl_trace_method_object = obj_desc;
acpi_gbl_original_dbg_level = acpi_dbg_level;
acpi_gbl_original_dbg_layer = acpi_dbg_layer;
acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
if (acpi_gbl_trace_dbg_level) {
acpi_dbg_level = acpi_gbl_trace_dbg_level;
}
if (acpi_gbl_trace_dbg_layer) {
acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
}
}
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
exit:
if (enabled) {
ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
obj_desc ? obj_desc->method.aml_start : NULL,
pathname);
}
if (pathname) {
ACPI_FREE(pathname);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_stop_trace_method
*
* PARAMETERS: method_node - Node of the method
* obj_desc - The method object
* walk_state - current state, NULL if not yet executing
* a method.
*
* RETURN: None
*
* DESCRIPTION: Stop control method execution trace
*
******************************************************************************/
void
acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
char *pathname = NULL;
u8 enabled;
ACPI_FUNCTION_NAME(ex_stop_trace_method);
if (method_node) {
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit_path;
}
enabled = acpi_ex_interpreter_trace_enabled(NULL);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (enabled) {
ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
obj_desc ? obj_desc->method.aml_start : NULL,
pathname);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit_path;
}
/* Check whether the tracer should be stopped */
if (acpi_gbl_trace_method_object == obj_desc) {
/* Disable further tracing if type is one-shot */
if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
acpi_gbl_trace_method_name = NULL;
}
acpi_dbg_level = acpi_gbl_original_dbg_level;
acpi_dbg_layer = acpi_gbl_original_dbg_layer;
acpi_gbl_trace_method_object = NULL;
}
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
exit_path:
if (pathname) {
ACPI_FREE(pathname);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_start_trace_opcode
*
* PARAMETERS: op - The parser opcode object
* walk_state - current state, NULL if not yet executing
* a method.
*
* RETURN: None
*
* DESCRIPTION: Start opcode execution trace
*
******************************************************************************/
void
acpi_ex_start_trace_opcode(union acpi_parse_object *op,
struct acpi_walk_state *walk_state)
{
ACPI_FUNCTION_NAME(ex_start_trace_opcode);
if (acpi_ex_interpreter_trace_enabled(NULL) &&
(acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
op->common.aml, op->common.aml_op_name);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_stop_trace_opcode
*
* PARAMETERS: op - The parser opcode object
* walk_state - current state, NULL if not yet executing
* a method.
*
* RETURN: None
*
* DESCRIPTION: Stop opcode execution trace
*
******************************************************************************/
void
acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
struct acpi_walk_state *walk_state)
{
ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
if (acpi_ex_interpreter_trace_enabled(NULL) &&
(acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
op->common.aml, op->common.aml_op_name);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,536 +0,0 @@
/******************************************************************************
*
* Module Name: exfield - ACPI AML (p-code) execution - field manipulation
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exfield")
/* Local prototypes */
static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_serial_access_length
*
* PARAMETERS: accessor_type - The type of the protocol indicated by region
* field access attributes
* access_length - The access length of the region field
*
* RETURN: Decoded access length
*
* DESCRIPTION: This routine returns the length of the generic_serial_bus
* protocol bytes
*
******************************************************************************/
static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
{
u32 length;
switch (accessor_type) {
case AML_FIELD_ATTRIB_QUICK:
length = 0;
break;
case AML_FIELD_ATTRIB_SEND_RCV:
case AML_FIELD_ATTRIB_BYTE:
length = 1;
break;
case AML_FIELD_ATTRIB_WORD:
case AML_FIELD_ATTRIB_WORD_CALL:
length = 2;
break;
case AML_FIELD_ATTRIB_MULTIBYTE:
case AML_FIELD_ATTRIB_RAW_BYTES:
case AML_FIELD_ATTRIB_RAW_PROCESS:
length = access_length;
break;
case AML_FIELD_ATTRIB_BLOCK:
case AML_FIELD_ATTRIB_BLOCK_CALL:
default:
length = ACPI_GSBUS_BUFFER_SIZE - 2;
break;
}
return (length);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_read_data_from_field
*
* PARAMETERS: walk_state - Current execution state
* obj_desc - The named field
* ret_buffer_desc - Where the return data object is stored
*
* RETURN: Status
*
* DESCRIPTION: Read from a named field. Returns either an Integer or a
* Buffer, depending on the size of the field.
*
******************************************************************************/
acpi_status
acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
union acpi_operand_object *obj_desc,
union acpi_operand_object **ret_buffer_desc)
{
acpi_status status;
union acpi_operand_object *buffer_desc;
acpi_size length;
void *buffer;
u32 function;
u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
/* Parameter validation */
if (!obj_desc) {
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
if (!ret_buffer_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = acpi_ds_get_buffer_field_arguments(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
* the data and then directly access the region handler.
*
* Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
*/
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_READ | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
accessor_type = obj_desc->field.attribute;
length = acpi_ex_get_serial_access_length(accessor_type,
obj_desc->
field.
access_length);
/*
* Add additional 2 bytes for the generic_serial_bus data buffer:
*
* Status; (Byte 0 of the data buffer)
* Length; (Byte 1 of the data buffer)
* Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_READ | (accessor_type << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_READ;
}
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Call the region handler for the read */
status = acpi_ex_access_region(obj_desc, 0,
ACPI_CAST_PTR(u64,
buffer_desc->
buffer.pointer),
function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
goto exit;
}
/*
* Allocate a buffer for the contents of the field.
*
* If the field is larger than the current integer width, create
* a BUFFER to hold it. Otherwise, use an INTEGER. This allows
* the use of arithmetic operators on the returned value if the
* field size is equal or smaller than an Integer.
*
* Note: Field.length is in bits.
*/
length =
(acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
if (length > acpi_gbl_integer_byte_width) {
/* Field is too large for an Integer, create a Buffer instead */
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
} else {
/* Field will fit within an Integer (normal case) */
buffer_desc = acpi_ut_create_integer_object((u64) 0);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
length = acpi_gbl_integer_byte_width;
buffer = &buffer_desc->integer.value;
}
if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GPIO)) {
/*
* For GPIO (general_purpose_io), the Address will be the bit offset
* from the previous Connection() operator, making it effectively a
* pin number index. The bit_length is the length of the field, which
* is thus the number of pins.
*/
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"GPIO FieldRead [FROM]: Pin %u Bits %u\n",
obj_desc->field.pin_number_index,
obj_desc->field.bit_length));
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Perform the write */
status = acpi_ex_access_region(obj_desc, 0,
(u64 *)buffer, ACPI_READ);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(buffer_desc);
} else {
*ret_buffer_desc = buffer_desc;
}
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
obj_desc, obj_desc->common.type, buffer,
(u32) length));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
obj_desc->common_field.bit_length,
obj_desc->common_field.start_field_bit_offset,
obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Read from the field */
status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
exit:
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(buffer_desc);
} else {
*ret_buffer_desc = buffer_desc;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_write_data_to_field
*
* PARAMETERS: source_desc - Contains data to write
* obj_desc - The named field
* result_desc - Where the return value is returned, if any
*
* RETURN: Status
*
* DESCRIPTION: Write to a named field
*
******************************************************************************/
acpi_status
acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc)
{
acpi_status status;
u32 length;
void *buffer;
union acpi_operand_object *buffer_desc;
u32 function;
u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
/* Parameter validation */
if (!source_desc || !obj_desc) {
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = acpi_ds_get_buffer_field_arguments(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus, GSBus or IPMI write. We will bypass the entire field
* mechanism and handoff the buffer directly to the handler. For
* these address spaces, the buffer is bi-directional; on a write,
* return data is returned in the same buffer.
*
* Source must be a buffer of sufficient size:
* ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
*
* Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
*/
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
"SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_WRITE | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
accessor_type = obj_desc->field.attribute;
length = acpi_ex_get_serial_access_length(accessor_type,
obj_desc->
field.
access_length);
/*
* Add additional 2 bytes for the generic_serial_bus data buffer:
*
* Status; (Byte 0 of the data buffer)
* Length; (Byte 1 of the data buffer)
* Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_WRITE | (accessor_type << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_WRITE;
}
if (source_desc->buffer.length < length) {
ACPI_ERROR((AE_INFO,
"SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
length, source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
/* Create the bi-directional buffer */
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
memcpy(buffer, source_desc->buffer.pointer, length);
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/*
* Perform the write (returns status and perhaps data in the
* same buffer)
*/
status = acpi_ex_access_region(obj_desc, 0,
(u64 *) buffer, function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
*result_desc = buffer_desc;
return_ACPI_STATUS(status);
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GPIO)) {
/*
* For GPIO (general_purpose_io), we will bypass the entire field
* mechanism and handoff the bit address and bit width directly to
* the handler. The Address will be the bit offset
* from the previous Connection() operator, making it effectively a
* pin number index. The bit_length is the length of the field, which
* is thus the number of pins.
*/
if (source_desc->common.type != ACPI_TYPE_INTEGER) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
acpi_ut_get_type_name(source_desc->common.
type),
source_desc->common.type,
(u32)source_desc->integer.value,
obj_desc->field.pin_number_index,
obj_desc->field.bit_length));
buffer = &source_desc->integer.value;
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Perform the write */
status = acpi_ex_access_region(obj_desc, 0,
(u64 *)buffer, ACPI_WRITE);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
return_ACPI_STATUS(status);
}
/* Get a pointer to the data to be written */
switch (source_desc->common.type) {
case ACPI_TYPE_INTEGER:
buffer = &source_desc->integer.value;
length = sizeof(source_desc->integer.value);
break;
case ACPI_TYPE_BUFFER:
buffer = source_desc->buffer.pointer;
length = source_desc->buffer.length;
break;
case ACPI_TYPE_STRING:
buffer = source_desc->string.pointer;
length = source_desc->string.length;
break;
default:
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
source_desc,
acpi_ut_get_type_name(source_desc->common.type),
source_desc->common.type, buffer, length));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
obj_desc,
acpi_ut_get_type_name(obj_desc->common.type),
obj_desc->common.type,
obj_desc->common_field.bit_length,
obj_desc->common_field.start_field_bit_offset,
obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Write to the field */
status = acpi_ex_insert_into_field(obj_desc, buffer, length);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
return_ACPI_STATUS(status);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,733 +0,0 @@
/******************************************************************************
*
* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#include "amlresrc.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmisc")
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_object_reference
*
* PARAMETERS: obj_desc - Create a reference to this object
* return_desc - Where to store the reference
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Obtain and return a "reference" to the target object
* Common code for the ref_of_op and the cond_ref_of_op.
*
******************************************************************************/
acpi_status
acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
union acpi_operand_object **return_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *reference_obj;
union acpi_operand_object *referenced_obj;
ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
*return_desc = NULL;
switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* Must be a reference to a Local or Arg
*/
switch (obj_desc->reference.class) {
case ACPI_REFCLASS_LOCAL:
case ACPI_REFCLASS_ARG:
case ACPI_REFCLASS_DEBUG:
/* The referenced object is the pseudo-node for the local/arg */
referenced_obj = obj_desc->reference.object;
break;
default:
ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
obj_desc->reference.class));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
break;
case ACPI_DESC_TYPE_NAMED:
/*
* A named reference that has already been resolved to a Node
*/
referenced_obj = obj_desc;
break;
default:
ACPI_ERROR((AE_INFO, "Invalid descriptor type 0x%X",
ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
return_ACPI_STATUS(AE_TYPE);
}
/* Create a new reference object */
reference_obj =
acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!reference_obj) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
reference_obj->reference.class = ACPI_REFCLASS_REFOF;
reference_obj->reference.object = referenced_obj;
*return_desc = reference_obj;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Object %p Type [%s], returning Reference %p\n",
obj_desc, acpi_ut_get_object_type_name(obj_desc),
*return_desc));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_concat_template
*
* PARAMETERS: operand0 - First source object
* operand1 - Second source object
* actual_return_desc - Where to place the return object
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Concatenate two resource templates
*
******************************************************************************/
acpi_status
acpi_ex_concat_template(union acpi_operand_object *operand0,
union acpi_operand_object *operand1,
union acpi_operand_object **actual_return_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *return_desc;
u8 *new_buf;
u8 *end_tag;
acpi_size length0;
acpi_size length1;
acpi_size new_length;
ACPI_FUNCTION_TRACE(ex_concat_template);
/*
* Find the end_tag descriptor in each resource template.
* Note1: returned pointers point TO the end_tag, not past it.
* Note2: zero-length buffers are allowed; treated like one end_tag
*/
/* Get the length of the first resource template */
status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
/* Get the length of the second resource template */
status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
/* Combine both lengths, minimum size will be 2 for end_tag */
new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
/* Create a new buffer object for the result (with one end_tag) */
return_desc = acpi_ut_create_buffer_object(new_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Copy the templates to the new buffer, 0 first, then 1 follows. One
* end_tag descriptor is copied from Operand1.
*/
new_buf = return_desc->buffer.pointer;
memcpy(new_buf, operand0->buffer.pointer, length0);
memcpy(new_buf + length0, operand1->buffer.pointer, length1);
/* Insert end_tag and set the checksum to zero, means "ignore checksum" */
new_buf[new_length - 1] = 0;
new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
/* Return the completed resource template */
*actual_return_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_concatenate
*
* PARAMETERS: operand0 - First source object
* operand1 - Second source object
* actual_return_desc - Where to place the return object
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
*
******************************************************************************/
acpi_status
acpi_ex_do_concatenate(union acpi_operand_object *operand0,
union acpi_operand_object *operand1,
union acpi_operand_object **actual_return_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *local_operand1 = operand1;
union acpi_operand_object *return_desc;
char *new_buf;
acpi_status status;
ACPI_FUNCTION_TRACE(ex_do_concatenate);
/*
* Convert the second operand if necessary. The first operand
* determines the type of the second operand, (See the Data Types
* section of the ACPI specification.) Both object types are
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
switch (operand0->common.type) {
case ACPI_TYPE_INTEGER:
status =
acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
status = acpi_ex_convert_to_string(operand1, &local_operand1,
ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
operand0->common.type));
status = AE_AML_INTERNAL;
}
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Both operands are now known to be the same object type
* (Both are Integer, String, or Buffer), and we can now perform the
* concatenation.
*/
/*
* There are three cases to handle:
*
* 1) Two Integers concatenated to produce a new Buffer
* 2) Two Strings concatenated to produce a new String
* 3) Two Buffers concatenated to produce a new Buffer
*/
switch (operand0->common.type) {
case ACPI_TYPE_INTEGER:
/* Result of two Integers is a Buffer */
/* Need enough buffer space for two integers */
return_desc = acpi_ut_create_buffer_object((acpi_size)
ACPI_MUL_2
(acpi_gbl_integer_byte_width));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
new_buf = (char *)return_desc->buffer.pointer;
/* Copy the first integer, LSB first */
memcpy(new_buf, &operand0->integer.value,
acpi_gbl_integer_byte_width);
/* Copy the second integer (LSB first) after the first */
memcpy(new_buf + acpi_gbl_integer_byte_width,
&local_operand1->integer.value,
acpi_gbl_integer_byte_width);
break;
case ACPI_TYPE_STRING:
/* Result of two Strings is a String */
return_desc = acpi_ut_create_string_object(((acpi_size)
operand0->string.
length +
local_operand1->
string.length));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
new_buf = return_desc->string.pointer;
/* Concatenate the strings */
strcpy(new_buf, operand0->string.pointer);
strcpy(new_buf + operand0->string.length,
local_operand1->string.pointer);
break;
case ACPI_TYPE_BUFFER:
/* Result of two Buffers is a Buffer */
return_desc = acpi_ut_create_buffer_object(((acpi_size)
operand0->buffer.
length +
local_operand1->
buffer.length));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
new_buf = (char *)return_desc->buffer.pointer;
/* Concatenate the buffers */
memcpy(new_buf, operand0->buffer.pointer,
operand0->buffer.length);
memcpy(new_buf + operand0->buffer.length,
local_operand1->buffer.pointer,
local_operand1->buffer.length);
break;
default:
/* Invalid object type, should not happen here */
ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
operand0->common.type));
status = AE_AML_INTERNAL;
goto cleanup;
}
*actual_return_desc = return_desc;
cleanup:
if (local_operand1 != operand1) {
acpi_ut_remove_reference(local_operand1);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_math_op
*
* PARAMETERS: opcode - AML opcode
* integer0 - Integer operand #0
* integer1 - Integer operand #1
*
* RETURN: Integer result of the operation
*
* DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
* math functions here is to prevent a lot of pointer dereferencing
* to obtain the operands.
*
******************************************************************************/
u64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1)
{
ACPI_FUNCTION_ENTRY();
switch (opcode) {
case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
return (integer0 + integer1);
case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
return (integer0 & integer1);
case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
return (~(integer0 & integer1));
case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
return (integer0 | integer1);
case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
return (~(integer0 | integer1));
case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
return (integer0 ^ integer1);
case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
return (integer0 * integer1);
case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
/*
* We need to check if the shiftcount is larger than the integer bit
* width since the behavior of this is not well-defined in the C language.
*/
if (integer1 >= acpi_gbl_integer_bit_width) {
return (0);
}
return (integer0 << integer1);
case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
/*
* We need to check if the shiftcount is larger than the integer bit
* width since the behavior of this is not well-defined in the C language.
*/
if (integer1 >= acpi_gbl_integer_bit_width) {
return (0);
}
return (integer0 >> integer1);
case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
return (integer0 - integer1);
default:
return (0);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_numeric_op
*
* PARAMETERS: opcode - AML opcode
* integer0 - Integer operand #0
* integer1 - Integer operand #1
* logical_result - TRUE/FALSE result of the operation
*
* RETURN: Status
*
* DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
* operators (LAnd and LOr), both operands must be integers.
*
* Note: cleanest machine code seems to be produced by the code
* below, rather than using statements of the form:
* Result = (Integer0 && Integer1);
*
******************************************************************************/
acpi_status
acpi_ex_do_logical_numeric_op(u16 opcode,
u64 integer0, u64 integer1, u8 *logical_result)
{
acpi_status status = AE_OK;
u8 local_result = FALSE;
ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
switch (opcode) {
case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
if (integer0 && integer1) {
local_result = TRUE;
}
break;
case AML_LOR_OP: /* LOr (Integer0, Integer1) */
if (integer0 || integer1) {
local_result = TRUE;
}
break;
default:
status = AE_AML_INTERNAL;
break;
}
/* Return the logical result and status */
*logical_result = local_result;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_op
*
* PARAMETERS: opcode - AML opcode
* operand0 - operand #0
* operand1 - operand #1
* logical_result - TRUE/FALSE result of the operation
*
* RETURN: Status
*
* DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
* functions here is to prevent a lot of pointer dereferencing
* to obtain the operands and to simplify the generation of the
* logical value. For the Numeric operators (LAnd and LOr), both
* operands must be integers. For the other logical operators,
* operands can be any combination of Integer/String/Buffer. The
* first operand determines the type to which the second operand
* will be converted.
*
* Note: cleanest machine code seems to be produced by the code
* below, rather than using statements of the form:
* Result = (Operand0 == Operand1);
*
******************************************************************************/
acpi_status
acpi_ex_do_logical_op(u16 opcode,
union acpi_operand_object *operand0,
union acpi_operand_object *operand1, u8 * logical_result)
{
union acpi_operand_object *local_operand1 = operand1;
u64 integer0;
u64 integer1;
u32 length0;
u32 length1;
acpi_status status = AE_OK;
u8 local_result = FALSE;
int compare;
ACPI_FUNCTION_TRACE(ex_do_logical_op);
/*
* Convert the second operand if necessary. The first operand
* determines the type of the second operand, (See the Data Types
* section of the ACPI 3.0+ specification.) Both object types are
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
switch (operand0->common.type) {
case ACPI_TYPE_INTEGER:
status =
acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
status = acpi_ex_convert_to_string(operand1, &local_operand1,
ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
status = AE_AML_INTERNAL;
break;
}
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Two cases: 1) Both Integers, 2) Both Strings or Buffers
*/
if (operand0->common.type == ACPI_TYPE_INTEGER) {
/*
* 1) Both operands are of type integer
* Note: local_operand1 may have changed above
*/
integer0 = operand0->integer.value;
integer1 = local_operand1->integer.value;
switch (opcode) {
case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
if (integer0 == integer1) {
local_result = TRUE;
}
break;
case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (integer0 > integer1) {
local_result = TRUE;
}
break;
case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (integer0 < integer1) {
local_result = TRUE;
}
break;
default:
status = AE_AML_INTERNAL;
break;
}
} else {
/*
* 2) Both operands are Strings or both are Buffers
* Note: Code below takes advantage of common Buffer/String
* object fields. local_operand1 may have changed above. Use
* memcmp to handle nulls in buffers.
*/
length0 = operand0->buffer.length;
length1 = local_operand1->buffer.length;
/* Lexicographic compare: compare the data bytes */
compare = memcmp(operand0->buffer.pointer,
local_operand1->buffer.pointer,
(length0 > length1) ? length1 : length0);
switch (opcode) {
case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
/* Length and all bytes must be equal */
if ((length0 == length1) && (compare == 0)) {
/* Length and all bytes match ==> TRUE */
local_result = TRUE;
}
break;
case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (compare > 0) {
local_result = TRUE;
goto cleanup; /* TRUE */
}
if (compare < 0) {
goto cleanup; /* FALSE */
}
/* Bytes match (to shortest length), compare lengths */
if (length0 > length1) {
local_result = TRUE;
}
break;
case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (compare > 0) {
goto cleanup; /* FALSE */
}
if (compare < 0) {
local_result = TRUE;
goto cleanup; /* TRUE */
}
/* Bytes match (to shortest length), compare lengths */
if (length0 < length1) {
local_result = TRUE;
}
break;
default:
status = AE_AML_INTERNAL;
break;
}
}
cleanup:
/* New object was created if implicit conversion performed - delete */
if (local_operand1 != operand1) {
acpi_ut_remove_reference(local_operand1);
}
/* Return the logical result and status */
*logical_result = local_result;
return_ACPI_STATUS(status);
}

View File

@@ -1,502 +0,0 @@
/******************************************************************************
*
* Module Name: exmutex - ASL Mutex Acquire/Release functions
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "acevents.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmutex")
/* Local prototypes */
static void
acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
struct acpi_thread_state *thread);
/*******************************************************************************
*
* FUNCTION: acpi_ex_unlink_mutex
*
* PARAMETERS: obj_desc - The mutex to be unlinked
*
* RETURN: None
*
* DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
*
******************************************************************************/
void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
{
struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
if (!thread) {
return;
}
/* Doubly linked list */
if (obj_desc->mutex.next) {
(obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
}
if (obj_desc->mutex.prev) {
(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
/*
* Migrate the previous sync level associated with this mutex to
* the previous mutex on the list so that it may be preserved.
* This handles the case where several mutexes have been acquired
* at the same level, but are not released in opposite order.
*/
(obj_desc->mutex.prev)->mutex.original_sync_level =
obj_desc->mutex.original_sync_level;
} else {
thread->acquired_mutex_list = obj_desc->mutex.next;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_link_mutex
*
* PARAMETERS: obj_desc - The mutex to be linked
* thread - Current executing thread object
*
* RETURN: None
*
* DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
*
******************************************************************************/
static void
acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
struct acpi_thread_state *thread)
{
union acpi_operand_object *list_head;
list_head = thread->acquired_mutex_list;
/* This object will be the first object in the list */
obj_desc->mutex.prev = NULL;
obj_desc->mutex.next = list_head;
/* Update old first object to point back to this object */
if (list_head) {
list_head->mutex.prev = obj_desc;
}
/* Update list head */
thread->acquired_mutex_list = obj_desc;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_mutex_object
*
* PARAMETERS: timeout - Timeout in milliseconds
* obj_desc - Mutex object
* thread_id - Current thread state
*
* RETURN: Status
*
* DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
* path that supports multiple acquires by the same thread.
*
* MUTEX: Interpreter must be locked
*
* NOTE: This interface is called from three places:
* 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator
* 2) From acpi_ex_acquire_global_lock when an AML Field access requires the
* global lock
* 3) From the external interface, acpi_acquire_global_lock
*
******************************************************************************/
acpi_status
acpi_ex_acquire_mutex_object(u16 timeout,
union acpi_operand_object *obj_desc,
acpi_thread_id thread_id)
{
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Support for multiple acquires by the owning thread */
if (obj_desc->mutex.thread_id == thread_id) {
/*
* The mutex is already owned by this thread, just increment the
* acquisition depth
*/
obj_desc->mutex.acquisition_depth++;
return_ACPI_STATUS(AE_OK);
}
/* Acquire the mutex, wait if necessary. Special case for Global Lock */
if (obj_desc == acpi_gbl_global_lock_mutex) {
status = acpi_ev_acquire_global_lock(timeout);
} else {
status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
timeout);
}
if (ACPI_FAILURE(status)) {
/* Includes failure from a timeout on time_desc */
return_ACPI_STATUS(status);
}
/* Acquired the mutex: update mutex object */
obj_desc->mutex.thread_id = thread_id;
obj_desc->mutex.acquisition_depth = 1;
obj_desc->mutex.original_sync_level = 0;
obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_mutex
*
* PARAMETERS: time_desc - Timeout integer
* obj_desc - Mutex object
* walk_state - Current method execution state
*
* RETURN: Status
*
* DESCRIPTION: Acquire an AML mutex
*
******************************************************************************/
acpi_status
acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Must have a valid thread state struct */
if (!walk_state->thread) {
ACPI_ERROR((AE_INFO,
"Cannot acquire Mutex [%4.4s], null thread info",
acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* Current sync level must be less than or equal to the sync level of the
* mutex. This mechanism provides some deadlock prevention
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
ACPI_ERROR((AE_INFO,
"Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
acpi_ut_get_node_name(obj_desc->mutex.node),
walk_state->thread->current_sync_level));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
obj_desc,
walk_state->thread->thread_id);
if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
/* Save Thread object, original/current sync levels */
obj_desc->mutex.owner_thread = walk_state->thread;
obj_desc->mutex.original_sync_level =
walk_state->thread->current_sync_level;
walk_state->thread->current_sync_level =
obj_desc->mutex.sync_level;
/* Link the mutex to the current thread for force-unlock at method exit */
acpi_ex_link_mutex(obj_desc, walk_state->thread);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_mutex_object
*
* PARAMETERS: obj_desc - The object descriptor for this op
*
* RETURN: Status
*
* DESCRIPTION: Release a previously acquired Mutex, low level interface.
* Provides a common path that supports multiple releases (after
* previous multiple acquires) by the same thread.
*
* MUTEX: Interpreter must be locked
*
* NOTE: This interface is called from three places:
* 1) From acpi_ex_release_mutex, via an AML Acquire() operator
* 2) From acpi_ex_release_global_lock when an AML Field access requires the
* global lock
* 3) From the external interface, acpi_release_global_lock
*
******************************************************************************/
acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_release_mutex_object);
if (obj_desc->mutex.acquisition_depth == 0) {
return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
/* Match multiple Acquires with multiple Releases */
obj_desc->mutex.acquisition_depth--;
if (obj_desc->mutex.acquisition_depth != 0) {
/* Just decrement the depth and return */
return_ACPI_STATUS(AE_OK);
}
if (obj_desc->mutex.owner_thread) {
/* Unlink the mutex from the owner's list */
acpi_ex_unlink_mutex(obj_desc);
obj_desc->mutex.owner_thread = NULL;
}
/* Release the mutex, special case for Global Lock */
if (obj_desc == acpi_gbl_global_lock_mutex) {
status = acpi_ev_release_global_lock();
} else {
acpi_os_release_mutex(obj_desc->mutex.os_mutex);
}
/* Clear mutex info */
obj_desc->mutex.thread_id = 0;
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_mutex
*
* PARAMETERS: obj_desc - The object descriptor for this op
* walk_state - Current method execution state
*
* RETURN: Status
*
* DESCRIPTION: Release a previously acquired Mutex.
*
******************************************************************************/
acpi_status
acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
u8 previous_sync_level;
struct acpi_thread_state *owner_thread;
ACPI_FUNCTION_TRACE(ex_release_mutex);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
owner_thread = obj_desc->mutex.owner_thread;
/* The mutex must have been previously acquired in order to release it */
if (!owner_thread) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], not acquired",
acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
}
/* Must have a valid thread ID */
if (!walk_state->thread) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], null thread info",
acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* The Mutex is owned, but this thread must be the owner.
* Special case for Global Lock, any thread can release
*/
if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
(obj_desc != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
"Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
(u32)walk_state->thread->thread_id,
acpi_ut_get_node_name(obj_desc->mutex.node),
(u32)owner_thread->thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
/*
* The sync level of the mutex must be equal to the current sync level. In
* other words, the current level means that at least one mutex at that
* level is currently being held. Attempting to release a mutex of a
* different level can only mean that the mutex ordering rule is being
* violated. This behavior is clarified in ACPI 4.0 specification.
*/
if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
acpi_ut_get_node_name(obj_desc->mutex.node),
obj_desc->mutex.sync_level,
walk_state->thread->current_sync_level));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/*
* Get the previous sync_level from the head of the acquired mutex list.
* This handles the case where several mutexes at the same level have been
* acquired, but are not released in reverse order.
*/
previous_sync_level =
owner_thread->acquired_mutex_list->mutex.original_sync_level;
status = acpi_ex_release_mutex_object(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (obj_desc->mutex.acquisition_depth == 0) {
/* Restore the previous sync_level */
owner_thread->current_sync_level = previous_sync_level;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_all_mutexes
*
* PARAMETERS: thread - Current executing thread object
*
* RETURN: Status
*
* DESCRIPTION: Release all mutexes held by this thread
*
* NOTE: This function is called as the thread is exiting the interpreter.
* Mutexes are not released when an individual control method is exited, but
* only when the parent thread actually exits the interpreter. This allows one
* method to acquire a mutex, and a different method to release it, as long as
* this is performed underneath a single parent control method.
*
******************************************************************************/
void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
{
union acpi_operand_object *next = thread->acquired_mutex_list;
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_NAME(ex_release_all_mutexes);
/* Traverse the list of owned mutexes, releasing each one */
while (next) {
obj_desc = next;
next = obj_desc->mutex.next;
obj_desc->mutex.prev = NULL;
obj_desc->mutex.next = NULL;
obj_desc->mutex.acquisition_depth = 0;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Force-releasing held mutex: %p\n",
obj_desc));
/* Release the mutex, special case for Global Lock */
if (obj_desc == acpi_gbl_global_lock_mutex) {
/* Ignore errors */
(void)acpi_ev_release_global_lock();
} else {
acpi_os_release_mutex(obj_desc->mutex.os_mutex);
}
/* Mark mutex unowned */
obj_desc->mutex.owner_thread = NULL;
obj_desc->mutex.thread_id = 0;
/* Update Thread sync_level (Last mutex is the important one) */
thread->current_sync_level =
obj_desc->mutex.original_sync_level;
}
}

View File

@@ -1,435 +0,0 @@
/******************************************************************************
*
* Module Name: exnames - interpreter/scanner name load/execute
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exnames")
/* Local prototypes */
static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
/*******************************************************************************
*
* FUNCTION: acpi_ex_allocate_name_string
*
* PARAMETERS: prefix_count - Count of parent levels. Special cases:
* (-1)==root, 0==none
* num_name_segs - count of 4-character name segments
*
* RETURN: A pointer to the allocated string segment. This segment must
* be deleted by the caller.
*
* DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
* string is long enough, and set up prefix if any.
*
******************************************************************************/
static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
{
char *temp_ptr;
char *name_string;
u32 size_needed;
ACPI_FUNCTION_TRACE(ex_allocate_name_string);
/*
* Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
* Also, one byte for the null terminator.
* This may actually be somewhat longer than needed.
*/
if (prefix_count == ACPI_UINT32_MAX) {
/* Special case for root */
size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
} else {
size_needed =
prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
}
/*
* Allocate a buffer for the name.
* This buffer must be deleted by the caller!
*/
name_string = ACPI_ALLOCATE(size_needed);
if (!name_string) {
ACPI_ERROR((AE_INFO,
"Could not allocate size %u", size_needed));
return_PTR(NULL);
}
temp_ptr = name_string;
/* Set up Root or Parent prefixes if needed */
if (prefix_count == ACPI_UINT32_MAX) {
*temp_ptr++ = AML_ROOT_PREFIX;
} else {
while (prefix_count--) {
*temp_ptr++ = AML_PARENT_PREFIX;
}
}
/* Set up Dual or Multi prefixes if needed */
if (num_name_segs > 2) {
/* Set up multi prefixes */
*temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
*temp_ptr++ = (char)num_name_segs;
} else if (2 == num_name_segs) {
/* Set up dual prefixes */
*temp_ptr++ = AML_DUAL_NAME_PREFIX;
}
/*
* Terminate string following prefixes. acpi_ex_name_segment() will
* append the segment(s)
*/
*temp_ptr = 0;
return_PTR(name_string);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_name_segment
*
* PARAMETERS: in_aml_address - Pointer to the name in the AML code
* name_string - Where to return the name. The name is appended
* to any existing string to form a namepath
*
* RETURN: Status
*
* DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
*
******************************************************************************/
static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
{
char *aml_address = (void *)*in_aml_address;
acpi_status status = AE_OK;
u32 index;
char char_buf[5];
ACPI_FUNCTION_TRACE(ex_name_segment);
/*
* If first character is a digit, then we know that we aren't looking at a
* valid name segment
*/
char_buf[0] = *aml_address;
if ('0' <= char_buf[0] && char_buf[0] <= '9') {
ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
return_ACPI_STATUS(AE_CTRL_PENDING);
}
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
for (index = 0;
(index < ACPI_NAME_SIZE)
&& (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
char_buf[index] = *aml_address++;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
}
/* Valid name segment */
if (index == 4) {
/* Found 4 valid characters */
char_buf[4] = '\0';
if (name_string) {
strcat(name_string, char_buf);
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Appended to - %s\n", name_string));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"No Name string - %s\n", char_buf));
}
} else if (index == 0) {
/*
* First character was not a valid name character,
* so we are looking at something other than a name.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Leading character is not alpha: %02Xh (not a name)\n",
char_buf[0]));
status = AE_CTRL_PENDING;
} else {
/*
* Segment started with one or more valid characters, but fewer than
* the required 4
*/
status = AE_AML_BAD_NAME;
ACPI_ERROR((AE_INFO,
"Bad character 0x%02x in name, at %p",
*aml_address, aml_address));
}
*in_aml_address = ACPI_CAST_PTR(u8, aml_address);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_name_string
*
* PARAMETERS: data_type - Object type to be associated with this
* name
* in_aml_address - Pointer to the namestring in the AML code
* out_name_string - Where the namestring is returned
* out_name_length - Length of the returned string
*
* RETURN: Status, namestring and length
*
* DESCRIPTION: Extract a full namepath from the AML byte stream,
* including any prefixes.
*
******************************************************************************/
acpi_status
acpi_ex_get_name_string(acpi_object_type data_type,
u8 * in_aml_address,
char **out_name_string, u32 * out_name_length)
{
acpi_status status = AE_OK;
u8 *aml_address = in_aml_address;
char *name_string = NULL;
u32 num_segments;
u32 prefix_count = 0;
u8 has_prefix = FALSE;
ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
/* Disallow prefixes for types associated with field_unit names */
name_string = acpi_ex_allocate_name_string(0, 1);
if (!name_string) {
status = AE_NO_MEMORY;
} else {
status =
acpi_ex_name_segment(&aml_address, name_string);
}
} else {
/*
* data_type is not a field name.
* Examine first character of name for root or parent prefix operators
*/
switch (*aml_address) {
case AML_ROOT_PREFIX:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"RootPrefix(\\) at %p\n",
aml_address));
/*
* Remember that we have a root_prefix --
* see comment in acpi_ex_allocate_name_string()
*/
aml_address++;
prefix_count = ACPI_UINT32_MAX;
has_prefix = TRUE;
break;
case AML_PARENT_PREFIX:
/* Increment past possibly multiple parent prefixes */
do {
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"ParentPrefix (^) at %p\n",
aml_address));
aml_address++;
prefix_count++;
} while (*aml_address == AML_PARENT_PREFIX);
has_prefix = TRUE;
break;
default:
/* Not a prefix character */
break;
}
/* Examine first character of name for name segment prefix operator */
switch (*aml_address) {
case AML_DUAL_NAME_PREFIX:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"DualNamePrefix at %p\n",
aml_address));
aml_address++;
name_string =
acpi_ex_allocate_name_string(prefix_count, 2);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
/* Indicate that we processed a prefix */
has_prefix = TRUE;
status =
acpi_ex_name_segment(&aml_address, name_string);
if (ACPI_SUCCESS(status)) {
status =
acpi_ex_name_segment(&aml_address,
name_string);
}
break;
case AML_MULTI_NAME_PREFIX_OP:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"MultiNamePrefix at %p\n",
aml_address));
/* Fetch count of segments remaining in name path */
aml_address++;
num_segments = *aml_address;
name_string =
acpi_ex_allocate_name_string(prefix_count,
num_segments);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
/* Indicate that we processed a prefix */
aml_address++;
has_prefix = TRUE;
while (num_segments &&
(status =
acpi_ex_name_segment(&aml_address,
name_string)) == AE_OK) {
num_segments--;
}
break;
case 0:
/* null_name valid as of 8-12-98 ASL/AML Grammar Update */
if (prefix_count == ACPI_UINT32_MAX) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"NameSeg is \"\\\" followed by NULL\n"));
}
/* Consume the NULL byte */
aml_address++;
name_string =
acpi_ex_allocate_name_string(prefix_count, 0);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
break;
default:
/* Name segment string */
name_string =
acpi_ex_allocate_name_string(prefix_count, 1);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
status =
acpi_ex_name_segment(&aml_address, name_string);
break;
}
}
if (AE_CTRL_PENDING == status && has_prefix) {
/* Ran out of segments after processing a prefix */
ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
status = AE_AML_BAD_NAME;
}
if (ACPI_FAILURE(status)) {
if (name_string) {
ACPI_FREE(name_string);
}
return_ACPI_STATUS(status);
}
*out_name_string = name_string;
*out_name_length = (u32) (aml_address - in_aml_address);
return_ACPI_STATUS(status);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,584 +0,0 @@
/******************************************************************************
*
* Module Name: exoparg2 - AML execution - opcodes with 2 arguments
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acparser.h"
#include "acinterp.h"
#include "acevents.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg2")
/*!
* Naming convention for AML interpreter execution routines.
*
* The routines that begin execution of AML opcodes are named with a common
* convention based upon the number of arguments, the number of target operands,
* and whether or not a value is returned:
*
* AcpiExOpcode_xA_yT_zR
*
* Where:
*
* xA - ARGUMENTS: The number of arguments (input operands) that are
* required for this opcode type (1 through 6 args).
* yT - TARGETS: The number of targets (output operands) that are required
* for this opcode type (0, 1, or 2 targets).
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
* as the function return (0 or 1).
*
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_0R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute opcode with two arguments, no target, and no return
* value.
*
* ALLOCATION: Deletes both operands
*
******************************************************************************/
acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
struct acpi_namespace_node *node;
u32 value;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the opcode */
switch (walk_state->opcode) {
case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
/* The first operand is a namespace node */
node = (struct acpi_namespace_node *)operand[0];
/* Second value is the notify value */
value = (u32) operand[1]->integer.value;
/* Are notifies allowed on this object? */
if (!acpi_ev_is_notify_object(node)) {
ACPI_ERROR((AE_INFO,
"Unexpected notify object type [%s]",
acpi_ut_get_type_name(node->type)));
status = AE_AML_OPERAND_TYPE;
break;
}
/*
* Dispatch the notify to the appropriate handler
* NOTE: the request is queued for execution after this method
* completes. The notify handlers are NOT invoked synchronously
* from this thread -- because handlers may in turn run other
* control methods.
*/
status = acpi_ev_queue_notify_request(node, value);
break;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_2T_1R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
* and one implicit return value.
*
******************************************************************************/
acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *return_desc1 = NULL;
union acpi_operand_object *return_desc2 = NULL;
acpi_status status;
ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
switch (walk_state->opcode) {
case AML_DIVIDE_OP:
/* Divide (Dividend, Divisor, remainder_result quotient_result) */
return_desc1 =
acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc1) {
status = AE_NO_MEMORY;
goto cleanup;
}
return_desc2 =
acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc2) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Quotient to return_desc1, remainder to return_desc2 */
status = acpi_ut_divide(operand[0]->integer.value,
operand[1]->integer.value,
&return_desc1->integer.value,
&return_desc2->integer.value);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
break;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the results to the target reference operands */
status = acpi_ex_store(return_desc2, operand[2], walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
status = acpi_ex_store(return_desc1, operand[3], walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
cleanup:
/*
* Since the remainder is not returned indirectly, remove a reference to
* it. Only the quotient is returned indirectly.
*/
acpi_ut_remove_reference(return_desc2);
if (ACPI_FAILURE(status)) {
/* Delete the return object */
acpi_ut_remove_reference(return_desc1);
}
/* Save return object (the remainder) on success */
else {
walk_state->result_obj = return_desc1;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_1T_1R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute opcode with two arguments, one target, and a return
* value.
*
******************************************************************************/
acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *return_desc = NULL;
u64 index;
acpi_status status = AE_OK;
acpi_size length = 0;
ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
if (walk_state->op_info->flags & AML_MATH) {
/* All simple math opcodes (add, etc.) */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
return_desc->integer.value =
acpi_ex_do_math_op(walk_state->opcode,
operand[0]->integer.value,
operand[1]->integer.value);
goto store_result_to_target;
}
switch (walk_state->opcode) {
case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* return_desc will contain the remainder */
status = acpi_ut_divide(operand[0]->integer.value,
operand[1]->integer.value,
NULL, &return_desc->integer.value);
break;
case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
status = acpi_ex_do_concatenate(operand[0], operand[1],
&return_desc, walk_state);
break;
case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
/*
* Input object is guaranteed to be a buffer at this point (it may have
* been converted.) Copy the raw buffer data to a new object of
* type String.
*/
/*
* Get the length of the new string. It is the smallest of:
* 1) Length of the input buffer
* 2) Max length as specified in the to_string operator
* 3) Length of input buffer up to a zero byte (null terminator)
*
* NOTE: A length of zero is ok, and will create a zero-length, null
* terminated string.
*/
while ((length < operand[0]->buffer.length) &&
(length < operand[1]->integer.value) &&
(operand[0]->buffer.pointer[length])) {
length++;
}
/* Allocate a new string object */
return_desc = acpi_ut_create_string_object(length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* Copy the raw buffer data with no transform.
* (NULL terminated already)
*/
memcpy(return_desc->string.pointer,
operand[0]->buffer.pointer, length);
break;
case AML_CONCAT_RES_OP:
/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
status = acpi_ex_concat_template(operand[0], operand[1],
&return_desc, walk_state);
break;
case AML_INDEX_OP: /* Index (Source Index Result) */
/* Create the internal return object */
return_desc =
acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Initialize the Index reference object */
index = operand[1]->integer.value;
return_desc->reference.value = (u32) index;
return_desc->reference.class = ACPI_REFCLASS_INDEX;
/*
* At this point, the Source operand is a String, Buffer, or Package.
* Verify that the index is within range.
*/
switch ((operand[0])->common.type) {
case ACPI_TYPE_STRING:
if (index >= operand[0]->string.length) {
length = operand[0]->string.length;
status = AE_AML_STRING_LIMIT;
}
return_desc->reference.target_type =
ACPI_TYPE_BUFFER_FIELD;
return_desc->reference.index_pointer =
&(operand[0]->buffer.pointer[index]);
break;
case ACPI_TYPE_BUFFER:
if (index >= operand[0]->buffer.length) {
length = operand[0]->buffer.length;
status = AE_AML_BUFFER_LIMIT;
}
return_desc->reference.target_type =
ACPI_TYPE_BUFFER_FIELD;
return_desc->reference.index_pointer =
&(operand[0]->buffer.pointer[index]);
break;
case ACPI_TYPE_PACKAGE:
if (index >= operand[0]->package.count) {
length = operand[0]->package.count;
status = AE_AML_PACKAGE_LIMIT;
}
return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
return_desc->reference.where =
&operand[0]->package.elements[index];
break;
default:
status = AE_AML_INTERNAL;
goto cleanup;
}
/* Failure means that the Index was beyond the end of the object */
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
ACPI_FORMAT_UINT64(index),
(u32)length));
goto cleanup;
}
/*
* Save the target object and add a reference to it for the life
* of the index
*/
return_desc->reference.object = operand[0];
acpi_ut_add_reference(operand[0]);
/* Store the reference to the Target */
status = acpi_ex_store(return_desc, operand[2], walk_state);
/* Return the reference */
walk_state->result_obj = return_desc;
goto cleanup;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
store_result_to_target:
if (ACPI_SUCCESS(status)) {
/*
* Store the result of the operation (which is now in return_desc) into
* the Target descriptor.
*/
status = acpi_ex_store(return_desc, operand[2], walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
if (!walk_state->result_obj) {
walk_state->result_obj = return_desc;
}
}
cleanup:
/* Delete return object on error */
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_1R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
*
******************************************************************************/
acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *return_desc = NULL;
acpi_status status = AE_OK;
u8 logical_result = FALSE;
ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Create the internal return object */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Execute the Opcode */
if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
/* logical_op (Operand0, Operand1) */
status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
operand[0]->integer.
value,
operand[1]->integer.
value, &logical_result);
goto store_logical_result;
} else if (walk_state->op_info->flags & AML_LOGICAL) {
/* logical_op (Operand0, Operand1) */
status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
operand[1], &logical_result);
goto store_logical_result;
}
switch (walk_state->opcode) {
case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
status =
acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
if (status == AE_TIME) {
logical_result = TRUE; /* TRUE = Acquire timed out */
status = AE_OK;
}
break;
case AML_WAIT_OP: /* Wait (event_object, Timeout) */
status = acpi_ex_system_wait_event(operand[1], operand[0]);
if (status == AE_TIME) {
logical_result = TRUE; /* TRUE, Wait timed out */
status = AE_OK;
}
break;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
store_logical_result:
/*
* Set return value to according to logical_result. logical TRUE (all ones)
* Default is FALSE (zero)
*/
if (logical_result) {
return_desc->integer.value = ACPI_UINT64_MAX;
}
cleanup:
/* Delete return object on error */
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
}
/* Save return object on success */
else {
walk_state->result_obj = return_desc;
}
return_ACPI_STATUS(status);
}

View File

@@ -1,281 +0,0 @@
/******************************************************************************
*
* Module Name: exoparg3 - AML execution - opcodes with 3 arguments
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "acparser.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg3")
/*!
* Naming convention for AML interpreter execution routines.
*
* The routines that begin execution of AML opcodes are named with a common
* convention based upon the number of arguments, the number of target operands,
* and whether or not a value is returned:
*
* AcpiExOpcode_xA_yT_zR
*
* Where:
*
* xA - ARGUMENTS: The number of arguments (input operands) that are
* required for this opcode type (1 through 6 args).
* yT - TARGETS: The number of targets (output operands) that are required
* for this opcode type (0, 1, or 2 targets).
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
* as the function return (0 or 1).
*
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_0T_0R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute Triadic operator (3 operands)
*
******************************************************************************/
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
struct acpi_signal_fatal_info *fatal;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
(u32) operand[0]->integer.value,
(u32) operand[1]->integer.value,
(u32) operand[2]->integer.value));
fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
if (fatal) {
fatal->type = (u32) operand[0]->integer.value;
fatal->code = (u32) operand[1]->integer.value;
fatal->argument = (u32) operand[2]->integer.value;
}
/* Always signal the OS! */
status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
/* Might return while OS is shutting down, just continue */
ACPI_FREE(fatal);
goto cleanup;
case AML_EXTERNAL_OP:
/*
* If the interpreter sees this opcode, just ignore it. The External
* op is intended for use by disassemblers in order to properly
* disassemble control method invocations. The opcode or group of
* opcodes should be surrounded by an "if (0)" clause to ensure that
* AML interpreters never see the opcode.
*/
status = AE_OK;
goto cleanup;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
cleanup:
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_1T_1R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute Triadic operator (3 operands)
*
******************************************************************************/
acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *return_desc = NULL;
char *buffer = NULL;
acpi_status status = AE_OK;
u64 index;
acpi_size length;
ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
/*
* Create the return object. The Source operand is guaranteed to be
* either a String or a Buffer, so just use its type.
*/
return_desc = acpi_ut_create_internal_object((operand[0])->
common.type);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Get the Integer values from the objects */
index = operand[1]->integer.value;
length = (acpi_size) operand[2]->integer.value;
/*
* If the index is beyond the length of the String/Buffer, or if the
* requested length is zero, return a zero-length String/Buffer
*/
if (index >= operand[0]->string.length) {
length = 0;
}
/* Truncate request if larger than the actual String/Buffer */
else if ((index + length) > operand[0]->string.length) {
length = (acpi_size) operand[0]->string.length -
(acpi_size) index;
}
/* Strings always have a sub-pointer, not so for buffers */
switch ((operand[0])->common.type) {
case ACPI_TYPE_STRING:
/* Always allocate a new buffer for the String */
buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
}
break;
case ACPI_TYPE_BUFFER:
/* If the requested length is zero, don't allocate a buffer */
if (length > 0) {
/* Allocate a new buffer for the Buffer */
buffer = ACPI_ALLOCATE_ZEROED(length);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
}
}
break;
default: /* Should not happen */
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
if (buffer) {
/* We have a buffer, copy the portion requested */
memcpy(buffer, operand[0]->string.pointer + index,
length);
}
/* Set the length of the new String/Buffer */
return_desc->string.pointer = buffer;
return_desc->string.length = (u32) length;
/* Mark buffer initialized */
return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
break;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the result in the target */
status = acpi_ex_store(return_desc, operand[3], walk_state);
cleanup:
/* Delete return object on error */
if (ACPI_FAILURE(status) || walk_state->result_obj) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
}
/* Set the return object and exit */
else {
walk_state->result_obj = return_desc;
}
return_ACPI_STATUS(status);
}

View File

@@ -1,332 +0,0 @@
/******************************************************************************
*
* Module Name: exoparg6 - AML execution - opcodes with 6 arguments
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "acparser.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg6")
/*!
* Naming convention for AML interpreter execution routines.
*
* The routines that begin execution of AML opcodes are named with a common
* convention based upon the number of arguments, the number of target operands,
* and whether or not a value is returned:
*
* AcpiExOpcode_xA_yT_zR
*
* Where:
*
* xA - ARGUMENTS: The number of arguments (input operands) that are
* required for this opcode type (1 through 6 args).
* yT - TARGETS: The number of targets (output operands) that are required
* for this opcode type (0, 1, or 2 targets).
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
* as the function return (0 or 1).
*
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
/* Local prototypes */
static u8
acpi_ex_do_match(u32 match_op,
union acpi_operand_object *package_obj,
union acpi_operand_object *match_obj);
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_match
*
* PARAMETERS: match_op - The AML match operand
* package_obj - Object from the target package
* match_obj - Object to be matched
*
* RETURN: TRUE if the match is successful, FALSE otherwise
*
* DESCRIPTION: Implements the low-level match for the ASL Match operator.
* Package elements will be implicitly converted to the type of
* the match object (Integer/Buffer/String).
*
******************************************************************************/
static u8
acpi_ex_do_match(u32 match_op,
union acpi_operand_object *package_obj,
union acpi_operand_object *match_obj)
{
u8 logical_result = TRUE;
acpi_status status;
/*
* Note: Since the package_obj/match_obj ordering is opposite to that of
* the standard logical operators, we have to reverse them when we call
* do_logical_op in order to make the implicit conversion rules work
* correctly. However, this means we have to flip the entire equation
* also. A bit ugly perhaps, but overall, better than fussing the
* parameters around at runtime, over and over again.
*
* Below, P[i] refers to the package element, M refers to the Match object.
*/
switch (match_op) {
case MATCH_MTR:
/* Always true */
break;
case MATCH_MEQ:
/*
* True if equal: (P[i] == M)
* Change to: (M == P[i])
*/
status =
acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
case MATCH_MLE:
/*
* True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
* Change to: (M >= P[i]) (M not_less than P[i])
*/
status =
acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
logical_result = (u8) ! logical_result;
break;
case MATCH_MLT:
/*
* True if less than: (P[i] < M)
* Change to: (M > P[i])
*/
status =
acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
package_obj, &logical_result);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
case MATCH_MGE:
/*
* True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
* Change to: (M <= P[i]) (M not_greater than P[i])
*/
status =
acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
package_obj, &logical_result);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
logical_result = (u8) ! logical_result;
break;
case MATCH_MGT:
/*
* True if greater than: (P[i] > M)
* Change to: (M < P[i])
*/
status =
acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
default:
/* Undefined */
return (FALSE);
}
return (logical_result);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_6A_0T_1R
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value
*
******************************************************************************/
acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
{
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *return_desc = NULL;
acpi_status status = AE_OK;
u64 index;
union acpi_operand_object *this_element;
ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_MATCH_OP:
/*
* Match (search_pkg[0], match_op1[1], match_obj1[2],
* match_op2[3], match_obj2[4], start_index[5])
*/
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
(operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
ACPI_ERROR((AE_INFO, "Match operator out of range"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
/* Get the package start_index, validate against the package length */
index = operand[5]->integer.value;
if (index >= operand[0]->package.count) {
ACPI_ERROR((AE_INFO,
"Index (0x%8.8X%8.8X) beyond package end (0x%X)",
ACPI_FORMAT_UINT64(index),
operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
/* Create an integer for the return value */
/* Default return value is ACPI_UINT64_MAX if no match found */
return_desc = acpi_ut_create_integer_object(ACPI_UINT64_MAX);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* Examine each element until a match is found. Both match conditions
* must be satisfied for a match to occur. Within the loop,
* "continue" signifies that the current element does not match
* and the next should be examined.
*
* Upon finding a match, the loop will terminate via "break" at
* the bottom. If it terminates "normally", match_value will be
* ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
for (; index < operand[0]->package.count; index++) {
/* Get the current package element */
this_element = operand[0]->package.elements[index];
/* Treat any uninitialized (NULL) elements as non-matching */
if (!this_element) {
continue;
}
/*
* Both match conditions must be satisfied. Execution of a continue
* (proceed to next iteration of enclosing for loop) signifies a
* non-match.
*/
if (!acpi_ex_do_match((u32) operand[1]->integer.value,
this_element, operand[2])) {
continue;
}
if (!acpi_ex_do_match((u32) operand[3]->integer.value,
this_element, operand[4])) {
continue;
}
/* Match found: Index is the return value */
return_desc->integer.value = index;
break;
}
break;
case AML_LOAD_TABLE_OP:
status = acpi_ex_load_table_op(walk_state, &return_desc);
break;
default:
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
cleanup:
/* Delete return object on error */
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
}
/* Save return object on success */
else {
walk_state->result_obj = return_desc;
}
return_ACPI_STATUS(status);
}

View File

@@ -1,630 +0,0 @@
/******************************************************************************
*
* Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exprep")
/* Local prototypes */
static u32
acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
u8 field_flags, u32 * return_byte_alignment);
#ifdef ACPI_UNDER_DEVELOPMENT
static u32
acpi_ex_generate_access(u32 field_bit_offset,
u32 field_bit_length, u32 region_length);
/*******************************************************************************
*
* FUNCTION: acpi_ex_generate_access
*
* PARAMETERS: field_bit_offset - Start of field within parent region/buffer
* field_bit_length - Length of field in bits
* region_length - Length of parent in bytes
*
* RETURN: Field granularity (8, 16, 32 or 64) and
* byte_alignment (1, 2, 3, or 4)
*
* DESCRIPTION: Generate an optimal access width for fields defined with the
* any_acc keyword.
*
* NOTE: Need to have the region_length in order to check for boundary
* conditions (end-of-region). However, the region_length is a deferred
* operation. Therefore, to complete this implementation, the generation
* of this access width must be deferred until the region length has
* been evaluated.
*
******************************************************************************/
static u32
acpi_ex_generate_access(u32 field_bit_offset,
u32 field_bit_length, u32 region_length)
{
u32 field_byte_length;
u32 field_byte_offset;
u32 field_byte_end_offset;
u32 access_byte_width;
u32 field_start_offset;
u32 field_end_offset;
u32 minimum_access_width = 0xFFFFFFFF;
u32 minimum_accesses = 0xFFFFFFFF;
u32 accesses;
ACPI_FUNCTION_TRACE(ex_generate_access);
/* Round Field start offset and length to "minimal" byte boundaries */
field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
field_bit_offset, 8));
field_byte_length = field_byte_end_offset - field_byte_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Bit length %u, Bit offset %u\n",
field_bit_length, field_bit_offset));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Byte Length %u, Byte Offset %u, End Offset %u\n",
field_byte_length, field_byte_offset,
field_byte_end_offset));
/*
* Iterative search for the maximum access width that is both aligned
* and does not go beyond the end of the region
*
* Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
*/
for (access_byte_width = 1; access_byte_width <= 8;
access_byte_width <<= 1) {
/*
* 1) Round end offset up to next access boundary and make sure that
* this does not go beyond the end of the parent region.
* 2) When the Access width is greater than the field_byte_length, we
* are done. (This does not optimize for the perfectly aligned
* case yet).
*/
if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <=
region_length) {
field_start_offset =
ACPI_ROUND_DOWN(field_byte_offset,
access_byte_width) /
access_byte_width;
field_end_offset =
ACPI_ROUND_UP((field_byte_length +
field_byte_offset),
access_byte_width) /
access_byte_width;
accesses = field_end_offset - field_start_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"AccessWidth %u end is within region\n",
access_byte_width));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Field Start %u, Field End %u -- requires %u accesses\n",
field_start_offset, field_end_offset,
accesses));
/* Single access is optimal */
if (accesses <= 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Entire field can be accessed with one operation of size %u\n",
access_byte_width));
return_VALUE(access_byte_width);
}
/*
* Fits in the region, but requires more than one read/write.
* try the next wider access on next iteration
*/
if (accesses < minimum_accesses) {
minimum_accesses = accesses;
minimum_access_width = access_byte_width;
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"AccessWidth %u end is NOT within region\n",
access_byte_width));
if (access_byte_width == 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Field goes beyond end-of-region!\n"));
/* Field does not fit in the region at all */
return_VALUE(0);
}
/*
* This width goes beyond the end-of-region, back off to
* previous access
*/
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Backing off to previous optimal access width of %u\n",
minimum_access_width));
return_VALUE(minimum_access_width);
}
}
/*
* Could not read/write field with one operation,
* just use max access width
*/
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Cannot access field in one operation, using width 8\n"));
return_VALUE(8);
}
#endif /* ACPI_UNDER_DEVELOPMENT */
/*******************************************************************************
*
* FUNCTION: acpi_ex_decode_field_access
*
* PARAMETERS: obj_desc - Field object
* field_flags - Encoded fieldflags (contains access bits)
* return_byte_alignment - Where the byte alignment is returned
*
* RETURN: Field granularity (8, 16, 32 or 64) and
* byte_alignment (1, 2, 3, or 4)
*
* DESCRIPTION: Decode the access_type bits of a field definition.
*
******************************************************************************/
static u32
acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
u8 field_flags, u32 * return_byte_alignment)
{
u32 access;
u32 byte_alignment;
u32 bit_length;
ACPI_FUNCTION_TRACE(ex_decode_field_access);
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
switch (access) {
case AML_FIELD_ACCESS_ANY:
#ifdef ACPI_UNDER_DEVELOPMENT
byte_alignment =
acpi_ex_generate_access(obj_desc->common_field.
start_field_bit_offset,
obj_desc->common_field.bit_length,
0xFFFFFFFF
/* Temp until we pass region_length as parameter */
);
bit_length = byte_alignment * 8;
#endif
byte_alignment = 1;
bit_length = 8;
break;
case AML_FIELD_ACCESS_BYTE:
case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
byte_alignment = 1;
bit_length = 8;
break;
case AML_FIELD_ACCESS_WORD:
byte_alignment = 2;
bit_length = 16;
break;
case AML_FIELD_ACCESS_DWORD:
byte_alignment = 4;
bit_length = 32;
break;
case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
byte_alignment = 8;
bit_length = 64;
break;
default:
/* Invalid field access type */
ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
return_UINT32(0);
}
if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
/*
* buffer_field access can be on any byte boundary, so the
* byte_alignment is always 1 byte -- regardless of any byte_alignment
* implied by the field access type.
*/
byte_alignment = 1;
}
*return_byte_alignment = byte_alignment;
return_UINT32(bit_length);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_common_field_object
*
* PARAMETERS: obj_desc - The field object
* field_flags - Access, lock_rule, and update_rule.
* The format of a field_flag is described
* in the ACPI specification
* field_attribute - Special attributes (not used)
* field_bit_position - Field start position
* field_bit_length - Field length in number of bits
*
* RETURN: Status
*
* DESCRIPTION: Initialize the areas of the field object that are common
* to the various types of fields. Note: This is very "sensitive"
* code because we are solving the general case for field
* alignment.
*
******************************************************************************/
acpi_status
acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
u8 field_flags,
u8 field_attribute,
u32 field_bit_position, u32 field_bit_length)
{
u32 access_bit_width;
u32 byte_alignment;
u32 nearest_byte_address;
ACPI_FUNCTION_TRACE(ex_prep_common_field_object);
/*
* Note: the structure being initialized is the
* ACPI_COMMON_FIELD_INFO; No structure fields outside of the common
* area are initialized by this procedure.
*/
obj_desc->common_field.field_flags = field_flags;
obj_desc->common_field.attribute = field_attribute;
obj_desc->common_field.bit_length = field_bit_length;
/*
* Decode the access type so we can compute offsets. The access type gives
* two pieces of information - the width of each field access and the
* necessary byte_alignment (address granularity) of the access.
*
* For any_acc, the access_bit_width is the largest width that is both
* necessary and possible in an attempt to access the whole field in one
* I/O operation. However, for any_acc, the byte_alignment is always one
* byte.
*
* For all Buffer Fields, the byte_alignment is always one byte.
*
* For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
* the same (equivalent) as the byte_alignment.
*/
access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags,
&byte_alignment);
if (!access_bit_width) {
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
/* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
obj_desc->common_field.access_byte_width = (u8)
ACPI_DIV_8(access_bit_width);
/*
* base_byte_offset is the address of the start of the field within the
* region. It is the byte address of the first *datum* (field-width data
* unit) of the field. (i.e., the first datum that contains at least the
* first *bit* of the field.)
*
* Note: byte_alignment is always either equal to the access_bit_width or 8
* (Byte access), and it defines the addressing granularity of the parent
* region or buffer.
*/
nearest_byte_address =
ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position);
obj_desc->common_field.base_byte_offset = (u32)
ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment);
/*
* start_field_bit_offset is the offset of the first bit of the field within
* a field datum.
*/
obj_desc->common_field.start_field_bit_offset = (u8)
(field_bit_position -
ACPI_MUL_8(obj_desc->common_field.base_byte_offset));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_field_value
*
* PARAMETERS: info - Contains all field creation info
*
* RETURN: Status
*
* DESCRIPTION: Construct an object of type union acpi_operand_object with a
* subtype of def_field and connect it to the parent Node.
*
******************************************************************************/
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
acpi_status status;
u32 access_byte_width;
u32 type;
ACPI_FUNCTION_TRACE(ex_prep_field_value);
/* Parameter validation */
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
if (!info->region_node) {
ACPI_ERROR((AE_INFO, "Null RegionNode"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
ACPI_ERROR((AE_INFO,
"Needed Region, found type 0x%X (%s)", type,
acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
/* Allocate a new field object */
obj_desc = acpi_ut_create_internal_object(info->field_type);
if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node;
status = acpi_ex_prep_common_field_object(obj_desc,
info->field_flags,
info->attribute,
info->field_bit_position,
info->field_bit_length);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(status);
}
/* Initialize areas of the object that are specific to the field type */
switch (info->field_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node);
/* Fields specific to generic_serial_bus fields */
obj_desc->field.access_length = info->access_length;
if (info->connection_node) {
second_desc = info->connection_node->object;
if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
status =
acpi_ds_get_buffer_arguments(second_desc);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(status);
}
}
obj_desc->field.resource_buffer =
second_desc->buffer.pointer;
obj_desc->field.resource_length =
(u16)second_desc->buffer.length;
} else if (info->resource_buffer) {
obj_desc->field.resource_buffer = info->resource_buffer;
obj_desc->field.resource_length = info->resource_length;
}
obj_desc->field.pin_number_index = info->pin_number_index;
/* Allow full data read from EC address space */
if ((obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_EC)
&& (obj_desc->common_field.bit_length > 8)) {
access_byte_width =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
bit_length);
/* Maximum byte width supported is 255 */
if (access_byte_width < 256) {
obj_desc->common_field.access_byte_width =
(u8)access_byte_width;
}
}
/* An additional reference for the container */
acpi_ut_add_reference(obj_desc->field.region_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
obj_desc->field.start_field_bit_offset,
obj_desc->field.base_byte_offset,
obj_desc->field.access_byte_width,
obj_desc->field.region_obj));
break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
obj_desc->bank_field.value = info->bank_value;
obj_desc->bank_field.region_obj =
acpi_ns_get_attached_object(info->region_node);
obj_desc->bank_field.bank_obj =
acpi_ns_get_attached_object(info->register_node);
/* An additional reference for the attached objects */
acpi_ut_add_reference(obj_desc->bank_field.region_obj);
acpi_ut_add_reference(obj_desc->bank_field.bank_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
obj_desc->bank_field.start_field_bit_offset,
obj_desc->bank_field.base_byte_offset,
obj_desc->field.access_byte_width,
obj_desc->bank_field.region_obj,
obj_desc->bank_field.bank_obj));
/*
* Remember location in AML stream of the field unit
* opcode and operands -- since the bank_value
* operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start =
ACPI_CAST_PTR(union acpi_parse_object,
info->data_register_node)->named.data;
second_desc->extra.aml_length =
ACPI_CAST_PTR(union acpi_parse_object,
info->data_register_node)->named.length;
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/* Get the Index and Data registers */
obj_desc->index_field.index_obj =
acpi_ns_get_attached_object(info->register_node);
obj_desc->index_field.data_obj =
acpi_ns_get_attached_object(info->data_register_node);
if (!obj_desc->index_field.data_obj
|| !obj_desc->index_field.index_obj) {
ACPI_ERROR((AE_INFO,
"Null Index Object during field prep"));
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* An additional reference for the attached objects */
acpi_ut_add_reference(obj_desc->index_field.data_obj);
acpi_ut_add_reference(obj_desc->index_field.index_obj);
/*
* April 2006: Changed to match MS behavior
*
* The value written to the Index register is the byte offset of the
* target field in units of the granularity of the index_field
*
* Previously, the value was calculated as an index in terms of the
* width of the Data register, as below:
*
* obj_desc->index_field.Value = (u32)
* (Info->field_bit_position / ACPI_MUL_8 (
* obj_desc->Field.access_byte_width));
*
* February 2006: Tried value as a byte offset:
* obj_desc->index_field.Value = (u32)
* ACPI_DIV_8 (Info->field_bit_position);
*/
obj_desc->index_field.value =
(u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
obj_desc->index_field.
access_byte_width);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
obj_desc->index_field.start_field_bit_offset,
obj_desc->index_field.base_byte_offset,
obj_desc->index_field.value,
obj_desc->field.access_byte_width,
obj_desc->index_field.index_obj,
obj_desc->index_field.data_obj));
break;
default:
/* No other types should get here */
break;
}
/*
* Store the constructed descriptor (obj_desc) into the parent Node,
* preserving the current type of that named_obj.
*/
status = acpi_ns_attach_object(info->field_node, obj_desc,
acpi_ns_get_type(info->field_node));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Set NamedObj %p [%4.4s], ObjDesc %p\n",
info->field_node,
acpi_ut_get_node_name(info->field_node), obj_desc));
/* Remove local reference to the object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}

View File

@@ -1,536 +0,0 @@
/******************************************************************************
*
* Module Name: exregion - ACPI default op_region (address space) handlers
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exregion")
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_memory_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the System Memory address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_system_memory_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
void *logical_addr_ptr = NULL;
struct acpi_mem_space_context *mem_info = region_context;
u32 length;
acpi_size map_length;
acpi_size page_boundary_map_length;
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
u32 remainder;
#endif
ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
/* Validate and translate the bit width */
switch (bit_width) {
case 8:
length = 1;
break;
case 16:
length = 2;
break;
case 32:
length = 4;
break;
case 64:
length = 8;
break;
default:
ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
bit_width));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
/*
* Hardware does not support non-aligned data transfers, we must verify
* the request.
*/
(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
if (remainder != 0) {
return_ACPI_STATUS(AE_AML_ALIGNMENT);
}
#endif
/*
* Does the request fit into the cached memory mapping?
* Is 1) Address below the current mapping? OR
* 2) Address beyond the current mapping?
*/
if ((address < mem_info->mapped_physical_address) ||
(((u64) address + length) > ((u64)
mem_info->mapped_physical_address +
mem_info->mapped_length))) {
/*
* The request cannot be resolved by the current memory mapping;
* Delete the existing mapping and create a new one.
*/
if (mem_info->mapped_length) {
/* Valid mapping, delete it */
acpi_os_unmap_memory(mem_info->mapped_logical_address,
mem_info->mapped_length);
}
/*
* October 2009: Attempt to map from the requested address to the
* end of the region. However, we will never map more than one
* page, nor will we cross a page boundary.
*/
map_length = (acpi_size)
((mem_info->address + mem_info->length) - address);
/*
* If mapping the entire remaining portion of the region will cross
* a page boundary, just map up to the page boundary, do not cross.
* On some systems, crossing a page boundary while mapping regions
* can cause warnings if the pages have different attributes
* due to resource management.
*
* This has the added benefit of constraining a single mapping to
* one page, which is similar to the original code that used a 4k
* maximum window.
*/
page_boundary_map_length = (acpi_size)
(ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
if (page_boundary_map_length == 0) {
page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
}
if (map_length > page_boundary_map_length) {
map_length = page_boundary_map_length;
}
/* Create a new mapping starting at the address given */
mem_info->mapped_logical_address =
acpi_os_map_memory(address, map_length);
if (!mem_info->mapped_logical_address) {
ACPI_ERROR((AE_INFO,
"Could not map memory at 0x%8.8X%8.8X, size %u",
ACPI_FORMAT_UINT64(address),
(u32)map_length));
mem_info->mapped_length = 0;
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the physical address and mapping size */
mem_info->mapped_physical_address = address;
mem_info->mapped_length = map_length;
}
/*
* Generate a logical pointer corresponding to the address we want to
* access
*/
logical_addr_ptr = mem_info->mapped_logical_address +
((u64) address - (u64) mem_info->mapped_physical_address);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
bit_width, function, ACPI_FORMAT_UINT64(address)));
/*
* Perform the memory read or write
*
* Note: For machines that do not support non-aligned transfers, the target
* address was checked for alignment above. We do not attempt to break the
* transfer up into smaller (byte-size) chunks because the AML specifically
* asked for a transfer width that the hardware may require.
*/
switch (function) {
case ACPI_READ:
*value = 0;
switch (bit_width) {
case 8:
*value = (u64)ACPI_GET8(logical_addr_ptr);
break;
case 16:
*value = (u64)ACPI_GET16(logical_addr_ptr);
break;
case 32:
*value = (u64)ACPI_GET32(logical_addr_ptr);
break;
case 64:
*value = (u64)ACPI_GET64(logical_addr_ptr);
break;
default:
/* bit_width was already validated */
break;
}
break;
case ACPI_WRITE:
switch (bit_width) {
case 8:
ACPI_SET8(logical_addr_ptr, *value);
break;
case 16:
ACPI_SET16(logical_addr_ptr, *value);
break;
case 32:
ACPI_SET32(logical_addr_ptr, *value);
break;
case 64:
ACPI_SET64(logical_addr_ptr, *value);
break;
default:
/* bit_width was already validated */
break;
}
break;
default:
status = AE_BAD_PARAMETER;
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_io_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the System IO address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_system_io_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
u32 value32;
ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
bit_width, function, ACPI_FORMAT_UINT64(address)));
/* Decode the function parameter */
switch (function) {
case ACPI_READ:
status = acpi_hw_read_port((acpi_io_address) address,
&value32, bit_width);
*value = value32;
break;
case ACPI_WRITE:
status = acpi_hw_write_port((acpi_io_address) address,
(u32) * value, bit_width);
break;
default:
status = AE_BAD_PARAMETER;
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_config_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the PCI Config address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_pci_config_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
struct acpi_pci_id *pci_id;
u16 pci_register;
ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
/*
* The arguments to acpi_os(Read|Write)pci_configuration are:
*
* pci_segment is the PCI bus segment range 0-31
* pci_bus is the PCI bus number range 0-255
* pci_device is the PCI device number range 0-31
* pci_function is the PCI device function number
* pci_register is the Config space register range 0-255 bytes
*
* value - input value for write, output address for read
*
*/
pci_id = (struct acpi_pci_id *)region_context;
pci_register = (u16) (u32) address;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
function, bit_width, pci_id->segment, pci_id->bus,
pci_id->device, pci_id->function, pci_register));
switch (function) {
case ACPI_READ:
*value = 0;
status = acpi_os_read_pci_configuration(pci_id, pci_register,
value, bit_width);
break;
case ACPI_WRITE:
status = acpi_os_write_pci_configuration(pci_id, pci_register,
*value, bit_width);
break;
default:
status = AE_BAD_PARAMETER;
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_cmos_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the CMOS address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_cmos_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_bar_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_pci_bar_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_data_table_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, or 32)
* value - Pointer to in or out value
* handler_context - Pointer to Handler's context
* region_context - Pointer to context specific to the
* accessed region
*
* RETURN: Status
*
* DESCRIPTION: Handler for the Data Table address space (Op Region)
*
******************************************************************************/
acpi_status
acpi_ex_data_table_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
/*
* Perform the memory read or write. The bit_width was already
* validated.
*/
switch (function) {
case ACPI_READ:
memcpy(ACPI_CAST_PTR(char, value),
ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width));
break;
case ACPI_WRITE:
memcpy(ACPI_PHYSADDR_TO_PTR(address),
ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
break;
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,279 +0,0 @@
/******************************************************************************
*
* Module Name: exresnte - AML Interpreter object resolution
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresnte")
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_node_to_value
*
* PARAMETERS: object_ptr - Pointer to a location that contains
* a pointer to a NS node, and will receive a
* pointer to the resolved object.
* walk_state - Current state. Valid only if executing AML
* code. NULL if simply resolving an object
*
* RETURN: Status
*
* DESCRIPTION: Resolve a Namespace node to a valued object
*
* Note: for some of the data types, the pointer attached to the Node
* can be either a pointer to an actual internal object or a pointer into the
* AML stream itself. These types are currently:
*
* ACPI_TYPE_INTEGER
* ACPI_TYPE_STRING
* ACPI_TYPE_BUFFER
* ACPI_TYPE_MUTEX
* ACPI_TYPE_PACKAGE
*
******************************************************************************/
acpi_status
acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_operand_object *source_desc;
union acpi_operand_object *obj_desc = NULL;
struct acpi_namespace_node *node;
acpi_object_type entry_type;
ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
/*
* The stack pointer points to a struct acpi_namespace_node (Node). Get the
* object that is attached to the Node.
*/
node = *object_ptr;
source_desc = acpi_ns_get_attached_object(node);
entry_type = acpi_ns_get_type((acpi_handle) node);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
node, source_desc,
acpi_ut_get_type_name(entry_type)));
if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
(entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/* There is always exactly one level of indirection */
node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
source_desc = acpi_ns_get_attached_object(node);
entry_type = acpi_ns_get_type((acpi_handle) node);
*object_ptr = node;
}
/*
* Several object types require no further processing:
* 1) Device/Thermal objects don't have a "real" subobject, return the Node
* 2) Method locals and arguments have a pseudo-Node
* 3) 10/2007: Added method type to assist with Package construction.
*/
if ((entry_type == ACPI_TYPE_DEVICE) ||
(entry_type == ACPI_TYPE_THERMAL) ||
(entry_type == ACPI_TYPE_METHOD) ||
(node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
return_ACPI_STATUS(AE_OK);
}
if (!source_desc) {
ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p",
node->name.ascii, node));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
}
/*
* Action is based on the type of the Node, which indicates the type
* of the attached object or pointer
*/
switch (entry_type) {
case ACPI_TYPE_PACKAGE:
if (source_desc->common.type != ACPI_TYPE_PACKAGE) {
ACPI_ERROR((AE_INFO, "Object not a Package, type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
status = acpi_ds_get_package_arguments(source_desc);
if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
}
break;
case ACPI_TYPE_BUFFER:
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
status = acpi_ds_get_buffer_arguments(source_desc);
if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
}
break;
case ACPI_TYPE_STRING:
if (source_desc->common.type != ACPI_TYPE_STRING) {
ACPI_ERROR((AE_INFO, "Object not a String, type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
case ACPI_TYPE_INTEGER:
if (source_desc->common.type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Object not a Integer, type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"FieldRead Node=%p SourceDesc=%p Type=%X\n",
node, source_desc, entry_type));
status =
acpi_ex_read_data_from_field(walk_state, source_desc,
&obj_desc);
break;
/* For these objects, just return the object attached to the Node */
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_EVENT:
case ACPI_TYPE_REGION:
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
/* TYPE_ANY is untyped, and thus there is no object associated with it */
case ACPI_TYPE_ANY:
ACPI_ERROR((AE_INFO,
"Untyped entry %p, no attached object!", node));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
case ACPI_TYPE_LOCAL_REFERENCE:
switch (source_desc->reference.class) {
case ACPI_REFCLASS_TABLE: /* This is a ddb_handle */
case ACPI_REFCLASS_REFOF:
case ACPI_REFCLASS_INDEX:
/* Return an additional reference to the object */
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
default:
/* No named references are allowed here */
ACPI_ERROR((AE_INFO,
"Unsupported Reference type 0x%X",
source_desc->reference.class));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
default:
/* Default case is for unknown types */
ACPI_ERROR((AE_INFO,
"Node %p - Unknown object type 0x%X",
node, entry_type));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
} /* switch (entry_type) */
/* Return the object descriptor */
*object_ptr = (void *)obj_desc;
return_ACPI_STATUS(status);
}

View File

@@ -1,559 +0,0 @@
/******************************************************************************
*
* Module Name: exresolv - AML Interpreter object resolution
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresolv")
/* Local prototypes */
static acpi_status
acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
struct acpi_walk_state *walk_state);
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_to_value
*
* PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can
* be either an (union acpi_operand_object *)
* or an acpi_handle.
* walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Convert Reference objects to values
*
******************************************************************************/
acpi_status
acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
struct acpi_walk_state *walk_state)
{
acpi_status status;
ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
if (!stack_ptr || !*stack_ptr) {
ACPI_ERROR((AE_INFO, "Internal - null pointer"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
* The entity pointed to by the stack_ptr can be either
* 1) A valid union acpi_operand_object, or
* 2) A struct acpi_namespace_node (named_obj)
*/
if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (!*stack_ptr) {
ACPI_ERROR((AE_INFO, "Internal - null pointer"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
}
/*
* Object on the stack may have changed if acpi_ex_resolve_object_to_value()
* was called (i.e., we can't use an _else_ here.)
*/
if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
status =
acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
(struct acpi_namespace_node,
stack_ptr), walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_object_to_value
*
* PARAMETERS: stack_ptr - Pointer to an internal object
* walk_state - Current method state
*
* RETURN: Status
*
* DESCRIPTION: Retrieve the value from an internal object. The Reference type
* uses the associated AML opcode to determine the value.
*
******************************************************************************/
static acpi_status
acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_operand_object *stack_desc;
union acpi_operand_object *obj_desc = NULL;
u8 ref_type;
ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
stack_desc = *stack_ptr;
/* This is an object of type union acpi_operand_object */
switch (stack_desc->common.type) {
case ACPI_TYPE_LOCAL_REFERENCE:
ref_type = stack_desc->reference.class;
switch (ref_type) {
case ACPI_REFCLASS_LOCAL:
case ACPI_REFCLASS_ARG:
/*
* Get the local from the method's state info
* Note: this increments the local's object reference count
*/
status = acpi_ds_method_data_get_value(ref_type,
stack_desc->
reference.value,
walk_state,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[Arg/Local %X] ValueObj is %p\n",
stack_desc->reference.value,
obj_desc));
/*
* Now we can delete the original Reference Object and
* replace it with the resolved value
*/
acpi_ut_remove_reference(stack_desc);
*stack_ptr = obj_desc;
break;
case ACPI_REFCLASS_INDEX:
switch (stack_desc->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
/* Just return - do not dereference */
break;
case ACPI_TYPE_PACKAGE:
/* If method call or copy_object - do not dereference */
if ((walk_state->opcode ==
AML_INT_METHODCALL_OP)
|| (walk_state->opcode == AML_COPY_OP)) {
break;
}
/* Otherwise, dereference the package_index to a package element */
obj_desc = *stack_desc->reference.where;
if (obj_desc) {
/*
* Valid object descriptor, copy pointer to return value
* (i.e., dereference the package index)
* Delete the ref object, increment the returned object
*/
acpi_ut_add_reference(obj_desc);
*stack_ptr = obj_desc;
} else {
/*
* A NULL object descriptor means an uninitialized element of
* the package, can't dereference it
*/
ACPI_ERROR((AE_INFO,
"Attempt to dereference an Index to NULL package element Idx=%p",
stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
break;
default:
/* Invalid reference object */
ACPI_ERROR((AE_INFO,
"Unknown TargetType 0x%X in Index/Reference object %p",
stack_desc->reference.target_type,
stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
case ACPI_REFCLASS_REFOF:
case ACPI_REFCLASS_DEBUG:
case ACPI_REFCLASS_TABLE:
/* Just leave the object as-is, do not dereference */
break;
case ACPI_REFCLASS_NAME: /* Reference to a named object */
/* Dereference the name */
if ((stack_desc->reference.node->type ==
ACPI_TYPE_DEVICE)
|| (stack_desc->reference.node->type ==
ACPI_TYPE_THERMAL)) {
/* These node types do not have 'real' subobjects */
*stack_ptr = (void *)stack_desc->reference.node;
} else {
/* Get the object pointed to by the namespace node */
*stack_ptr =
(stack_desc->reference.node)->object;
acpi_ut_add_reference(*stack_ptr);
}
acpi_ut_remove_reference(stack_desc);
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown Reference type 0x%X in %p",
ref_type, stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
case ACPI_TYPE_BUFFER:
status = acpi_ds_get_buffer_arguments(stack_desc);
break;
case ACPI_TYPE_PACKAGE:
status = acpi_ds_get_package_arguments(stack_desc);
break;
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"FieldRead SourceDesc=%p Type=%X\n",
stack_desc, stack_desc->common.type));
status =
acpi_ex_read_data_from_field(walk_state, stack_desc,
&obj_desc);
/* Remove a reference to the original operand, then override */
acpi_ut_remove_reference(*stack_ptr);
*stack_ptr = (void *)obj_desc;
break;
default:
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_multiple
*
* PARAMETERS: walk_state - Current state (contains AML opcode)
* operand - Starting point for resolution
* return_type - Where the object type is returned
* return_desc - Where the resolved object is returned
*
* RETURN: Status
*
* DESCRIPTION: Return the base object and type. Traverse a reference list if
* necessary to get to the base object.
*
******************************************************************************/
acpi_status
acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
union acpi_operand_object *operand,
acpi_object_type * return_type,
union acpi_operand_object **return_desc)
{
union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
struct acpi_namespace_node *node =
ACPI_CAST_PTR(struct acpi_namespace_node, operand);
acpi_object_type type;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
/* Operand can be either a namespace node or an operand descriptor */
switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
type = obj_desc->common.type;
break;
case ACPI_DESC_TYPE_NAMED:
type = ((struct acpi_namespace_node *)obj_desc)->type;
obj_desc = acpi_ns_get_attached_object(node);
/* If we had an Alias node, use the attached object for type info */
if (type == ACPI_TYPE_LOCAL_ALIAS) {
type = ((struct acpi_namespace_node *)obj_desc)->type;
obj_desc =
acpi_ns_get_attached_object((struct
acpi_namespace_node *)
obj_desc);
}
if (!obj_desc) {
ACPI_ERROR((AE_INFO,
"[%4.4s] Node is unresolved or uninitialized",
acpi_ut_get_node_name(node)));
return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
}
break;
default:
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* If type is anything other than a reference, we are done */
if (type != ACPI_TYPE_LOCAL_REFERENCE) {
goto exit;
}
/*
* For reference objects created via the ref_of, Index, or Load/load_table
* operators, we need to get to the base object (as per the ACPI
* specification of the object_type and size_of operators). This means
* traversing the list of possibly many nested references.
*/
while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.class) {
case ACPI_REFCLASS_REFOF:
case ACPI_REFCLASS_NAME:
/* Dereference the reference pointer */
if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
node = obj_desc->reference.object;
} else { /* AML_INT_NAMEPATH_OP */
node = obj_desc->reference.node;
}
/* All "References" point to a NS node */
if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
ACPI_DESC_TYPE_NAMED) {
ACPI_ERROR((AE_INFO,
"Not a namespace node %p [%s]",
node,
acpi_ut_get_descriptor_name(node)));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Get the attached object */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, use the NS node type */
type = acpi_ns_get_type(node);
goto exit;
}
/* Check for circular references */
if (obj_desc == operand) {
return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
}
break;
case ACPI_REFCLASS_INDEX:
/* Get the type of this reference (index into another object) */
type = obj_desc->reference.target_type;
if (type != ACPI_TYPE_PACKAGE) {
goto exit;
}
/*
* The main object is a package, we want to get the type
* of the individual package element that is referenced by
* the index.
*
* This could of course in turn be another reference object.
*/
obj_desc = *(obj_desc->reference.where);
if (!obj_desc) {
/* NULL package elements are allowed */
type = 0; /* Uninitialized */
goto exit;
}
break;
case ACPI_REFCLASS_TABLE:
type = ACPI_TYPE_DDB_HANDLE;
goto exit;
case ACPI_REFCLASS_LOCAL:
case ACPI_REFCLASS_ARG:
if (return_desc) {
status =
acpi_ds_method_data_get_value(obj_desc->
reference.
class,
obj_desc->
reference.
value,
walk_state,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_remove_reference(obj_desc);
} else {
status =
acpi_ds_method_data_get_node(obj_desc->
reference.
class,
obj_desc->
reference.
value,
walk_state,
&node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
type = ACPI_TYPE_ANY;
goto exit;
}
}
break;
case ACPI_REFCLASS_DEBUG:
/* The Debug Object is of type "DebugObject" */
type = ACPI_TYPE_DEBUG_OBJECT;
goto exit;
default:
ACPI_ERROR((AE_INFO,
"Unknown Reference Class 0x%2.2X",
obj_desc->reference.class));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
/*
* Now we are guaranteed to have an object that has not been created
* via the ref_of or Index operators.
*/
type = obj_desc->common.type;
exit:
/* Convert internal types to external types */
switch (type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
type = ACPI_TYPE_FIELD_UNIT;
break;
case ACPI_TYPE_LOCAL_SCOPE:
/* Per ACPI Specification, Scope is untyped */
type = ACPI_TYPE_ANY;
break;
default:
/* No change to Type required */
break;
}
*return_type = type;
if (return_desc) {
*return_desc = obj_desc;
}
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,703 +0,0 @@
/******************************************************************************
*
* Module Name: exresop - AML Interpreter operand/object resolution
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "amlcode.h"
#include "acparser.h"
#include "acinterp.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresop")
/* Local prototypes */
static acpi_status
acpi_ex_check_object_type(acpi_object_type type_needed,
acpi_object_type this_type, void *object);
/*******************************************************************************
*
* FUNCTION: acpi_ex_check_object_type
*
* PARAMETERS: type_needed Object type needed
* this_type Actual object type
* Object Object pointer
*
* RETURN: Status
*
* DESCRIPTION: Check required type against actual type
*
******************************************************************************/
static acpi_status
acpi_ex_check_object_type(acpi_object_type type_needed,
acpi_object_type this_type, void *object)
{
ACPI_FUNCTION_ENTRY();
if (type_needed == ACPI_TYPE_ANY) {
/* All types OK, so we don't perform any typechecks */
return (AE_OK);
}
if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
/*
* Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
* objects and thus allow them to be targets. (As per the ACPI
* specification, a store to a constant is a noop.)
*/
if ((this_type == ACPI_TYPE_INTEGER) &&
(((union acpi_operand_object *)object)->common.
flags & AOPOBJ_AML_CONSTANT)) {
return (AE_OK);
}
}
if (type_needed != this_type) {
ACPI_ERROR((AE_INFO,
"Needed type [%s], found [%s] %p",
acpi_ut_get_type_name(type_needed),
acpi_ut_get_type_name(this_type), object));
return (AE_AML_OPERAND_TYPE);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_operands
*
* PARAMETERS: opcode - Opcode being interpreted
* stack_ptr - Pointer to the operand stack to be
* resolved
* walk_state - Current state
*
* RETURN: Status
*
* DESCRIPTION: Convert multiple input operands to the types required by the
* target operator.
*
* Each 5-bit group in arg_types represents one required
* operand and indicates the required Type. The corresponding operand
* will be converted to the required type if possible, otherwise we
* abort with an exception.
*
******************************************************************************/
acpi_status
acpi_ex_resolve_operands(u16 opcode,
union acpi_operand_object ** stack_ptr,
struct acpi_walk_state * walk_state)
{
union acpi_operand_object *obj_desc;
acpi_status status = AE_OK;
u8 object_type;
u32 arg_types;
const struct acpi_opcode_info *op_info;
u32 this_arg_type;
acpi_object_type type_needed;
u16 target_op = 0;
ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode);
op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg_types = op_info->runtime_args;
if (arg_types == ARGI_INVALID_OPCODE) {
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", opcode));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Opcode %X [%s] RequiredOperandTypes=%8.8X\n",
opcode, op_info->name, arg_types));
/*
* Normal exit is with (arg_types == 0) at end of argument list.
* Function will return an exception from within the loop upon
* finding an entry which is not (or cannot be converted
* to) the required type; if stack underflows; or upon
* finding a NULL stack entry (which should not happen).
*/
while (GET_CURRENT_ARG_TYPE(arg_types)) {
if (!stack_ptr || !*stack_ptr) {
ACPI_ERROR((AE_INFO, "Null stack entry at %p",
stack_ptr));
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Extract useful items */
obj_desc = *stack_ptr;
/* Decode the descriptor type */
switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_NAMED:
/* Namespace Node */
object_type =
((struct acpi_namespace_node *)obj_desc)->type;
/*
* Resolve an alias object. The construction of these objects
* guarantees that there is only one level of alias indirection;
* thus, the attached object is always the aliased namespace node
*/
if (object_type == ACPI_TYPE_LOCAL_ALIAS) {
obj_desc =
acpi_ns_get_attached_object((struct
acpi_namespace_node
*)obj_desc);
*stack_ptr = obj_desc;
object_type =
((struct acpi_namespace_node *)obj_desc)->
type;
}
break;
case ACPI_DESC_TYPE_OPERAND:
/* ACPI internal object */
object_type = obj_desc->common.type;
/* Check for bad acpi_object_type */
if (!acpi_ut_valid_object_type(object_type)) {
ACPI_ERROR((AE_INFO,
"Bad operand object type [0x%X]",
object_type));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
/* Validate the Reference */
switch (obj_desc->reference.class) {
case ACPI_REFCLASS_DEBUG:
target_op = AML_DEBUG_OP;
/*lint -fallthrough */
case ACPI_REFCLASS_ARG:
case ACPI_REFCLASS_LOCAL:
case ACPI_REFCLASS_INDEX:
case ACPI_REFCLASS_REFOF:
case ACPI_REFCLASS_TABLE: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
case ACPI_REFCLASS_NAME: /* Reference to a named object */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Operand is a Reference, Class [%s] %2.2X\n",
acpi_ut_get_reference_name
(obj_desc),
obj_desc->reference.
class));
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown Reference Class 0x%2.2X in %p",
obj_desc->reference.class,
obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
break;
default:
/* Invalid descriptor */
ACPI_ERROR((AE_INFO, "Invalid descriptor %p [%s]",
obj_desc,
acpi_ut_get_descriptor_name(obj_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Get one argument type, point to the next */
this_arg_type = GET_CURRENT_ARG_TYPE(arg_types);
INCREMENT_ARG_LIST(arg_types);
/*
* Handle cases where the object does not need to be
* resolved to a value
*/
switch (this_arg_type) {
case ARGI_REF_OR_STRING: /* Can be a String or Reference */
if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
ACPI_DESC_TYPE_OPERAND)
&& (obj_desc->common.type == ACPI_TYPE_STRING)) {
/*
* String found - the string references a named object and
* must be resolved to a node
*/
goto next_operand;
}
/*
* Else not a string - fall through to the normal Reference
* case below
*/
/*lint -fallthrough */
case ARGI_REFERENCE: /* References: */
case ARGI_INTEGER_REF:
case ARGI_OBJECT_REF:
case ARGI_DEVICE_REF:
case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
case ARGI_SIMPLE_TARGET: /* Name, Local, or arg - no implicit conversion */
case ARGI_STORE_TARGET:
/*
* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE
* A Namespace Node is OK as-is
*/
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
ACPI_DESC_TYPE_NAMED) {
goto next_operand;
}
status =
acpi_ex_check_object_type(ACPI_TYPE_LOCAL_REFERENCE,
object_type, obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
goto next_operand;
case ARGI_DATAREFOBJ: /* Store operator only */
/*
* We don't want to resolve index_op reference objects during
* a store because this would be an implicit de_ref_of operation.
* Instead, we just want to store the reference object.
* -- All others must be resolved below.
*/
if ((opcode == AML_STORE_OP) &&
((*stack_ptr)->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
&& ((*stack_ptr)->reference.class ==
ACPI_REFCLASS_INDEX)) {
goto next_operand;
}
break;
default:
/* All cases covered above */
break;
}
/*
* Resolve this object to a value
*/
status = acpi_ex_resolve_to_value(stack_ptr, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the resolved object */
obj_desc = *stack_ptr;
/*
* Check the resulting object (value) type
*/
switch (this_arg_type) {
/*
* For the simple cases, only one type of resolved object
* is allowed
*/
case ARGI_MUTEX:
/* Need an operand of type ACPI_TYPE_MUTEX */
type_needed = ACPI_TYPE_MUTEX;
break;
case ARGI_EVENT:
/* Need an operand of type ACPI_TYPE_EVENT */
type_needed = ACPI_TYPE_EVENT;
break;
case ARGI_PACKAGE: /* Package */
/* Need an operand of type ACPI_TYPE_PACKAGE */
type_needed = ACPI_TYPE_PACKAGE;
break;
case ARGI_ANYTYPE:
/* Any operand type will do */
type_needed = ACPI_TYPE_ANY;
break;
case ARGI_DDBHANDLE:
/* Need an operand of type ACPI_TYPE_DDB_HANDLE */
type_needed = ACPI_TYPE_LOCAL_REFERENCE;
break;
/*
* The more complex cases allow multiple resolved object types
*/
case ARGI_INTEGER:
/*
* Need an operand of type ACPI_TYPE_INTEGER,
* But we can implicitly convert from a STRING or BUFFER
* aka - "Implicit Source Operand Conversion"
*/
status =
acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
ACPI_ERROR((AE_INFO,
"Needed [Integer/String/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
return_ACPI_STATUS(status);
}
if (obj_desc != *stack_ptr) {
acpi_ut_remove_reference(obj_desc);
}
goto next_operand;
case ARGI_BUFFER:
/*
* Need an operand of type ACPI_TYPE_BUFFER,
* But we can implicitly convert from a STRING or INTEGER
* aka - "Implicit Source Operand Conversion"
*/
status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
ACPI_ERROR((AE_INFO,
"Needed [Integer/String/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
return_ACPI_STATUS(status);
}
if (obj_desc != *stack_ptr) {
acpi_ut_remove_reference(obj_desc);
}
goto next_operand;
case ARGI_STRING:
/*
* Need an operand of type ACPI_TYPE_STRING,
* But we can implicitly convert from a BUFFER or INTEGER
* aka - "Implicit Source Operand Conversion"
*/
status = acpi_ex_convert_to_string(obj_desc, stack_ptr,
ACPI_IMPLICIT_CONVERT_HEX);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
ACPI_ERROR((AE_INFO,
"Needed [Integer/String/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
return_ACPI_STATUS(status);
}
if (obj_desc != *stack_ptr) {
acpi_ut_remove_reference(obj_desc);
}
goto next_operand;
case ARGI_COMPUTEDATA:
/* Need an operand of type INTEGER, STRING or BUFFER */
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
break;
default:
ACPI_ERROR((AE_INFO,
"Needed [Integer/String/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
case ARGI_BUFFER_OR_STRING:
/* Need an operand of type STRING or BUFFER */
switch (obj_desc->common.type) {
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
break;
case ACPI_TYPE_INTEGER:
/* Highest priority conversion is to type Buffer */
status =
acpi_ex_convert_to_buffer(obj_desc,
stack_ptr);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (obj_desc != *stack_ptr) {
acpi_ut_remove_reference(obj_desc);
}
break;
default:
ACPI_ERROR((AE_INFO,
"Needed [Integer/String/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
case ARGI_DATAOBJECT:
/*
* ARGI_DATAOBJECT is only used by the size_of operator.
* Need a buffer, string, package, or ref_of reference.
*
* The only reference allowed here is a direct reference to
* a namespace node.
*/
switch (obj_desc->common.type) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_LOCAL_REFERENCE:
/* Valid operand */
break;
default:
ACPI_ERROR((AE_INFO,
"Needed [Buffer/String/Package/Reference], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
case ARGI_COMPLEXOBJ:
/* Need a buffer or package or (ACPI 2.0) String */
switch (obj_desc->common.type) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
break;
default:
ACPI_ERROR((AE_INFO,
"Needed [Buffer/String/Package], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
case ARGI_REGION_OR_BUFFER: /* Used by Load() only */
/* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */
switch (obj_desc->common.type) {
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_REGION:
/* Valid operand */
break;
default:
ACPI_ERROR((AE_INFO,
"Needed [Region/Buffer], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
case ARGI_DATAREFOBJ:
/* Used by the Store() operator only */
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REFERENCE:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
case ACPI_TYPE_DDB_HANDLE:
/* Valid operand */
break;
default:
if (acpi_gbl_enable_interpreter_slack) {
/*
* Enable original behavior of Store(), allowing any and all
* objects as the source operand. The ACPI spec does not
* allow this, however.
*/
break;
}
if (target_op == AML_DEBUG_OP) {
/* Allow store of any object to the Debug object */
break;
}
ACPI_ERROR((AE_INFO,
"Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
default:
/* Unknown type */
ACPI_ERROR((AE_INFO,
"Internal - Unknown ARGI (required operand) type 0x%X",
this_arg_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Make sure that the original object was resolved to the
* required object type (Simple cases only).
*/
status = acpi_ex_check_object_type(type_needed,
(*stack_ptr)->common.type,
*stack_ptr);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
next_operand:
/*
* If more operands needed, decrement stack_ptr to point
* to next operand on stack
*/
if (GET_CURRENT_ARG_TYPE(arg_types)) {
stack_ptr--;
}
}
ACPI_DUMP_OPERANDS(walk_state->operands,
acpi_ps_get_opcode_name(opcode),
walk_state->num_operands);
return_ACPI_STATUS(status);
}

View File

@@ -1,619 +0,0 @@
/******************************************************************************
*
* Module Name: exstore - AML Interpreter object store support
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstore")
/* Local prototypes */
static acpi_status
acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
union acpi_operand_object *dest_desc,
struct acpi_walk_state *walk_state);
static acpi_status
acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
struct acpi_namespace_node *node,
struct acpi_walk_state *walk_state);
/*******************************************************************************
*
* FUNCTION: acpi_ex_store
*
* PARAMETERS: *source_desc - Value to be stored
* *dest_desc - Where to store it. Must be an NS node
* or union acpi_operand_object of type
* Reference;
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Store the value described by source_desc into the location
* described by dest_desc. Called by various interpreter
* functions to store the result of an operation into
* the destination operand -- not just simply the actual "Store"
* ASL operator.
*
******************************************************************************/
acpi_status
acpi_ex_store(union acpi_operand_object *source_desc,
union acpi_operand_object *dest_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_operand_object *ref_desc = dest_desc;
ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
/* Validate parameters */
if (!source_desc || !dest_desc) {
ACPI_ERROR((AE_INFO, "Null parameter"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/* dest_desc can be either a namespace node or an ACPI object */
if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
/*
* Dest is a namespace node,
* Storing an object into a Named node.
*/
status = acpi_ex_store_object_to_node(source_desc,
(struct
acpi_namespace_node *)
dest_desc, walk_state,
ACPI_IMPLICIT_CONVERSION);
return_ACPI_STATUS(status);
}
/* Destination object must be a Reference or a Constant object */
switch (dest_desc->common.type) {
case ACPI_TYPE_LOCAL_REFERENCE:
break;
case ACPI_TYPE_INTEGER:
/* Allow stores to Constants -- a Noop as per ACPI spec */
if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
return_ACPI_STATUS(AE_OK);
}
/*lint -fallthrough */
default:
/* Destination is not a Reference object */
ACPI_ERROR((AE_INFO,
"Target is not a Reference or Constant object - [%s] %p",
acpi_ut_get_object_type_name(dest_desc),
dest_desc));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* Examine the Reference class. These cases are handled:
*
* 1) Store to Name (Change the object associated with a name)
* 2) Store to an indexed area of a Buffer or Package
* 3) Store to a Method Local or Arg
* 4) Store to the debug object
*/
switch (ref_desc->reference.class) {
case ACPI_REFCLASS_REFOF:
/* Storing an object into a Name "container" */
status = acpi_ex_store_object_to_node(source_desc,
ref_desc->reference.
object, walk_state,
ACPI_IMPLICIT_CONVERSION);
break;
case ACPI_REFCLASS_INDEX:
/* Storing to an Index (pointer into a packager or buffer) */
status =
acpi_ex_store_object_to_index(source_desc, ref_desc,
walk_state);
break;
case ACPI_REFCLASS_LOCAL:
case ACPI_REFCLASS_ARG:
/* Store to a method local/arg */
status =
acpi_ds_store_object_to_local(ref_desc->reference.class,
ref_desc->reference.value,
source_desc, walk_state);
break;
case ACPI_REFCLASS_DEBUG:
/*
* Storing to the Debug object causes the value stored to be
* displayed and otherwise has no effect -- see ACPI Specification
*/
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"**** Write to Debug Object: Object %p [%s] ****:\n\n",
source_desc,
acpi_ut_get_object_type_name(source_desc)));
ACPI_DEBUG_OBJECT(source_desc, 0, 0);
break;
default:
ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
ref_desc->reference.class));
ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
status = AE_AML_INTERNAL;
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_index
*
* PARAMETERS: *source_desc - Value to be stored
* *dest_desc - Named object to receive the value
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Store the object to indexed Buffer or Package element
*
******************************************************************************/
static acpi_status
acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
union acpi_operand_object *index_desc,
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
union acpi_operand_object *new_desc;
u8 value = 0;
u32 i;
ACPI_FUNCTION_TRACE(ex_store_object_to_index);
/*
* Destination must be a reference pointer, and
* must point to either a buffer or a package
*/
switch (index_desc->reference.target_type) {
case ACPI_TYPE_PACKAGE:
/*
* Storing to a package element. Copy the object and replace
* any existing object with the new object. No implicit
* conversion is performed.
*
* The object at *(index_desc->Reference.Where) is the
* element within the package that is to be modified.
* The parent package object is at index_desc->Reference.Object
*/
obj_desc = *(index_desc->reference.where);
if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE &&
source_desc->reference.class == ACPI_REFCLASS_TABLE) {
/* This is a DDBHandle, just add a reference to it */
acpi_ut_add_reference(source_desc);
new_desc = source_desc;
} else {
/* Normal object, copy it */
status =
acpi_ut_copy_iobject_to_iobject(source_desc,
&new_desc,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
if (obj_desc) {
/* Decrement reference count by the ref count of the parent package */
for (i = 0; i < ((union acpi_operand_object *)
index_desc->reference.object)->common.
reference_count; i++) {
acpi_ut_remove_reference(obj_desc);
}
}
*(index_desc->reference.where) = new_desc;
/* Increment ref count by the ref count of the parent package-1 */
for (i = 1; i < ((union acpi_operand_object *)
index_desc->reference.object)->common.
reference_count; i++) {
acpi_ut_add_reference(new_desc);
}
break;
case ACPI_TYPE_BUFFER_FIELD:
/*
* Store into a Buffer or String (not actually a real buffer_field)
* at a location defined by an Index.
*
* The first 8-bit element of the source object is written to the
* 8-bit Buffer location defined by the Index destination object,
* according to the ACPI 2.0 specification.
*/
/*
* Make sure the target is a Buffer or String. An error should
* not happen here, since the reference_object was constructed
* by the INDEX_OP code.
*/
obj_desc = index_desc->reference.object;
if ((obj_desc->common.type != ACPI_TYPE_BUFFER) &&
(obj_desc->common.type != ACPI_TYPE_STRING)) {
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* The assignment of the individual elements will be slightly
* different for each source type.
*/
switch (source_desc->common.type) {
case ACPI_TYPE_INTEGER:
/* Use the least-significant byte of the integer */
value = (u8) (source_desc->integer.value);
break;
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
/* Note: Takes advantage of common string/buffer fields */
value = source_desc->buffer.pointer[0];
break;
default:
/* All other types are invalid */
ACPI_ERROR((AE_INFO,
"Source must be type [Integer/Buffer/String], found [%s]",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Store the source value into the target buffer byte */
obj_desc->buffer.pointer[index_desc->reference.value] = value;
break;
default:
ACPI_ERROR((AE_INFO,
"Target is not of type [Package/BufferField]"));
status = AE_AML_TARGET_TYPE;
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_node
*
* PARAMETERS: source_desc - Value to be stored
* node - Named object to receive the value
* walk_state - Current walk state
* implicit_conversion - Perform implicit conversion (yes/no)
*
* RETURN: Status
*
* DESCRIPTION: Store the object to the named object.
*
* The assignment of an object to a named object is handled here.
* The value passed in will replace the current value (if any)
* with the input value.
*
* When storing into an object the data is converted to the
* target object type then stored in the object. This means
* that the target object type (for an initialized target) will
* not be changed by a store operation. A copy_object can change
* the target type, however.
*
* The implicit_conversion flag is set to NO/FALSE only when
* storing to an arg_x -- as per the rules of the ACPI spec.
*
* Assumes parameters are already validated.
*
******************************************************************************/
acpi_status
acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
struct acpi_namespace_node *node,
struct acpi_walk_state *walk_state,
u8 implicit_conversion)
{
acpi_status status = AE_OK;
union acpi_operand_object *target_desc;
union acpi_operand_object *new_desc;
acpi_object_type target_type;
ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
/* Get current type of the node, and object attached to Node */
target_type = acpi_ns_get_type(node);
target_desc = acpi_ns_get_attached_object(node);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n",
source_desc,
acpi_ut_get_object_type_name(source_desc), node,
acpi_ut_get_type_name(target_type)));
/* Only limited target types possible for everything except copy_object */
if (walk_state->opcode != AML_COPY_OP) {
/*
* Only copy_object allows all object types to be overwritten. For
* target_ref(s), there are restrictions on the object types that
* are allowed.
*
* Allowable operations/typing for Store:
*
* 1) Simple Store
* Integer --> Integer (Named/Local/Arg)
* String --> String (Named/Local/Arg)
* Buffer --> Buffer (Named/Local/Arg)
* Package --> Package (Named/Local/Arg)
*
* 2) Store with implicit conversion
* Integer --> String or Buffer (Named)
* String --> Integer or Buffer (Named)
* Buffer --> Integer or String (Named)
*/
switch (target_type) {
case ACPI_TYPE_PACKAGE:
/*
* Here, can only store a package to an existing package.
* Storing a package to a Local/Arg is OK, and handled
* elsewhere.
*/
if (walk_state->opcode == AML_STORE_OP) {
if (source_desc->common.type !=
ACPI_TYPE_PACKAGE) {
ACPI_ERROR((AE_INFO,
"Cannot assign type [%s] to [Package] "
"(source must be type Pkg)",
acpi_ut_get_object_type_name
(source_desc)));
return_ACPI_STATUS(AE_AML_TARGET_TYPE);
}
break;
}
/* Fallthrough */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_EVENT:
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_REGION:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
ACPI_ERROR((AE_INFO,
"Target must be [Buffer/Integer/String/Reference], found [%s] (%4.4s)",
acpi_ut_get_type_name(node->type),
node->name.ascii));
return_ACPI_STATUS(AE_AML_TARGET_TYPE);
default:
break;
}
}
/*
* Resolve the source object to an actual value
* (If it is a reference object)
*/
status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Do the actual store operation */
switch (target_type) {
/*
* The simple data types all support implicit source operand
* conversion before the store.
*/
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) {
/*
* However, copy_object and Stores to arg_x do not perform
* an implicit conversion, as per the ACPI specification.
* A direct store is performed instead.
*/
status = acpi_ex_store_direct_to_node(source_desc, node,
walk_state);
break;
}
/* Store with implicit source operand conversion support */
status =
acpi_ex_store_object_to_object(source_desc, target_desc,
&new_desc, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (new_desc != target_desc) {
/*
* Store the new new_desc as the new value of the Name, and set
* the Name's type to that of the value being stored in it.
* source_desc reference count is incremented by attach_object.
*
* Note: This may change the type of the node if an explicit
* store has been performed such that the node/object type
* has been changed.
*/
status = acpi_ns_attach_object(node, new_desc,
new_desc->common.type);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Store type [%s] into [%s] via Convert/Attach\n",
acpi_ut_get_object_type_name
(source_desc),
acpi_ut_get_object_type_name
(new_desc)));
}
break;
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/*
* For all fields, always write the source data to the target
* field. Any required implicit source operand conversion is
* performed in the function below as necessary. Note, field
* objects must retain their original type permanently.
*/
status = acpi_ex_write_data_to_field(source_desc, target_desc,
&walk_state->result_obj);
break;
default:
/*
* copy_object operator: No conversions for all other types.
* Instead, directly store a copy of the source object.
*
* This is the ACPI spec-defined behavior for the copy_object
* operator. (Note, for this default case, all normal
* Store/Target operations exited above with an error).
*/
status = acpi_ex_store_direct_to_node(source_desc, node,
walk_state);
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_direct_to_node
*
* PARAMETERS: source_desc - Value to be stored
* node - Named object to receive the value
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: "Store" an object directly to a node. This involves a copy
* and an attach.
*
******************************************************************************/
static acpi_status
acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
struct acpi_namespace_node *node,
struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *new_desc;
ACPI_FUNCTION_TRACE(ex_store_direct_to_node);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Storing [%s] (%p) directly into node [%s] (%p)"
" with no implicit conversion\n",
acpi_ut_get_object_type_name(source_desc),
source_desc, acpi_ut_get_type_name(node->type),
node));
/* Copy the source object to a new object */
status =
acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Attach the new object to the node */
status = acpi_ns_attach_object(node, new_desc, new_desc->common.type);
acpi_ut_remove_reference(new_desc);
return_ACPI_STATUS(status);
}

View File

@@ -1,295 +0,0 @@
/******************************************************************************
*
* Module Name: exstoren - AML Interpreter object store support,
* Store to Node (namespace object)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstoren")
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_object
*
* PARAMETERS: source_desc_ptr - Pointer to the source object
* target_type - Current type of the target
* walk_state - Current walk state
*
* RETURN: Status, resolved object in source_desc_ptr.
*
* DESCRIPTION: Resolve an object. If the object is a reference, dereference
* it and return the actual object in the source_desc_ptr.
*
******************************************************************************/
acpi_status
acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
acpi_object_type target_type,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *source_desc = *source_desc_ptr;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_resolve_object);
/* Ensure we have a Target that can be stored to */
switch (target_type) {
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/*
* These cases all require only Integers or values that
* can be converted to Integers (Strings or Buffers)
*/
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/*
* Stores into a Field/Region or into a Integer/Buffer/String
* are all essentially the same. This case handles the
* "interchangeable" types Integer, String, and Buffer.
*/
if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
/* Resolve a reference object first */
status =
acpi_ex_resolve_to_value(source_desc_ptr,
walk_state);
if (ACPI_FAILURE(status)) {
break;
}
}
/* For copy_object, no further validation necessary */
if (walk_state->opcode == AML_COPY_OP) {
break;
}
/* Must have a Integer, Buffer, or String */
if ((source_desc->common.type != ACPI_TYPE_INTEGER) &&
(source_desc->common.type != ACPI_TYPE_BUFFER) &&
(source_desc->common.type != ACPI_TYPE_STRING) &&
!((source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
(source_desc->reference.class == ACPI_REFCLASS_TABLE))) {
/* Conversion successful but still not a valid type */
ACPI_ERROR((AE_INFO,
"Cannot assign type [%s] to [%s] (must be type Int/Str/Buf)",
acpi_ut_get_object_type_name(source_desc),
acpi_ut_get_type_name(target_type)));
status = AE_AML_OPERAND_TYPE;
}
break;
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
/*
* All aliases should have been resolved earlier, during the
* operand resolution phase.
*/
ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object"));
status = AE_AML_INTERNAL;
break;
case ACPI_TYPE_PACKAGE:
default:
/*
* All other types than Alias and the various Fields come here,
* including the untyped case - ACPI_TYPE_ANY.
*/
break;
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_object
*
* PARAMETERS: source_desc - Object to store
* dest_desc - Object to receive a copy of the source
* new_desc - New object if dest_desc is obsoleted
* walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: "Store" an object to another object. This may include
* converting the source type to the target type (implicit
* conversion), and a copy of the value of the source to
* the target.
*
* The Assignment of an object to another (not named) object
* is handled here.
* The Source passed in will replace the current value (if any)
* with the input value.
*
* When storing into an object the data is converted to the
* target object type then stored in the object. This means
* that the target object type (for an initialized target) will
* not be changed by a store operation.
*
* This module allows destination types of Number, String,
* Buffer, and Package.
*
* Assumes parameters are already validated. NOTE: source_desc
* resolution (from a reference object) must be performed by
* the caller if necessary.
*
******************************************************************************/
acpi_status
acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
union acpi_operand_object *dest_desc,
union acpi_operand_object **new_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc);
actual_src_desc = source_desc;
if (!dest_desc) {
/*
* There is no destination object (An uninitialized node or
* package element), so we can simply copy the source object
* creating a new destination object
*/
status =
acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc,
walk_state);
return_ACPI_STATUS(status);
}
if (source_desc->common.type != dest_desc->common.type) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
* of the target as per the ACPI specification.
*
* If no conversion performed, actual_src_desc = source_desc.
* Otherwise, actual_src_desc is a temporary object to hold the
* converted object.
*/
status = acpi_ex_convert_to_target_type(dest_desc->common.type,
source_desc,
&actual_src_desc,
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (source_desc == actual_src_desc) {
/*
* No conversion was performed. Return the source_desc as the
* new object.
*/
*new_desc = source_desc;
return_ACPI_STATUS(AE_OK);
}
}
/*
* We now have two objects of identical types, and we can perform a
* copy of the *value* of the source object.
*/
switch (dest_desc->common.type) {
case ACPI_TYPE_INTEGER:
dest_desc->integer.value = actual_src_desc->integer.value;
/* Truncate value if we are executing from a 32-bit ACPI table */
(void)acpi_ex_truncate_for32bit_table(dest_desc);
break;
case ACPI_TYPE_STRING:
status =
acpi_ex_store_string_to_string(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_BUFFER:
status =
acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_PACKAGE:
status =
acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc,
walk_state);
break;
default:
/*
* All other types come here.
*/
ACPI_WARNING((AE_INFO, "Store into type [%s] not implemented",
acpi_ut_get_object_type_name(dest_desc)));
status = AE_NOT_IMPLEMENTED;
break;
}
if (actual_src_desc != source_desc) {
/* Delete the intermediate (temporary) source object */
acpi_ut_remove_reference(actual_src_desc);
}
*new_desc = dest_desc;
return_ACPI_STATUS(status);
}

View File

@@ -1,220 +0,0 @@
/******************************************************************************
*
* Module Name: exstorob - AML Interpreter object store support, store to object
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstorob")
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_buffer_to_buffer
*
* PARAMETERS: source_desc - Source object to copy
* target_desc - Destination object of the copy
*
* RETURN: Status
*
* DESCRIPTION: Copy a buffer object to another buffer object.
*
******************************************************************************/
acpi_status
acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
u32 length;
u8 *buffer;
ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
/* If Source and Target are the same, just return */
if (source_desc == target_desc) {
return_ACPI_STATUS(AE_OK);
}
/* We know that source_desc is a buffer by now */
buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
length = source_desc->buffer.length;
/*
* If target is a buffer of length zero or is a static buffer,
* allocate a new buffer of the proper length
*/
if ((target_desc->buffer.length == 0) ||
(target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
target_desc->buffer.pointer = ACPI_ALLOCATE(length);
if (!target_desc->buffer.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->buffer.length = length;
}
/* Copy source buffer to target buffer */
if (length <= target_desc->buffer.length) {
/* Clear existing buffer and copy in the new one */
memset(target_desc->buffer.pointer, 0,
target_desc->buffer.length);
memcpy(target_desc->buffer.pointer, buffer, length);
#ifdef ACPI_OBSOLETE_BEHAVIOR
/*
* NOTE: ACPI versions up to 3.0 specified that the buffer must be
* truncated if the string is smaller than the buffer. However, "other"
* implementations of ACPI never did this and thus became the defacto
* standard. ACPI 3.0A changes this behavior such that the buffer
* is no longer truncated.
*/
/*
* OBSOLETE BEHAVIOR:
* If the original source was a string, we must truncate the buffer,
* according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
* copy must not truncate the original buffer.
*/
if (original_src_type == ACPI_TYPE_STRING) {
/* Set the new length of the target */
target_desc->buffer.length = length;
}
#endif
} else {
/* Truncate the source, copy only what will fit */
memcpy(target_desc->buffer.pointer, buffer,
target_desc->buffer.length);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Truncating source buffer from %X to %X\n",
length, target_desc->buffer.length));
}
/* Copy flags */
target_desc->buffer.flags = source_desc->buffer.flags;
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_string_to_string
*
* PARAMETERS: source_desc - Source object to copy
* target_desc - Destination object of the copy
*
* RETURN: Status
*
* DESCRIPTION: Copy a String object to another String object
*
******************************************************************************/
acpi_status
acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
u32 length;
u8 *buffer;
ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
/* If Source and Target are the same, just return */
if (source_desc == target_desc) {
return_ACPI_STATUS(AE_OK);
}
/* We know that source_desc is a string by now */
buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
length = source_desc->string.length;
/*
* Replace existing string value if it will fit and the string
* pointer is not a static pointer (part of an ACPI table)
*/
if ((length < target_desc->string.length) &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
/*
* String will fit in existing non-static buffer.
* Clear old string and copy in the new one
*/
memset(target_desc->string.pointer, 0,
(acpi_size) target_desc->string.length + 1);
memcpy(target_desc->string.pointer, buffer, length);
} else {
/*
* Free the current buffer, then allocate a new buffer
* large enough to hold the value
*/
if (target_desc->string.pointer &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
/* Only free if not a pointer into the DSDT */
ACPI_FREE(target_desc->string.pointer);
}
target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size)
length + 1);
if (!target_desc->string.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
memcpy(target_desc->string.pointer, buffer, length);
}
/* Set the new target length */
target_desc->string.length = length;
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,310 +0,0 @@
/******************************************************************************
*
* Module Name: exsystem - Interface to OS services
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exsystem")
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_wait_semaphore
*
* PARAMETERS: semaphore - Semaphore to wait on
* timeout - Max time to wait
*
* RETURN: Status
*
* DESCRIPTION: Implements a semaphore wait with a check to see if the
* semaphore is available immediately. If it is not, the
* interpreter is released before waiting.
*
******************************************************************************/
acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT);
if (ACPI_SUCCESS(status)) {
return_ACPI_STATUS(status);
}
if (status == AE_TIME) {
/* We must wait, so unlock the interpreter */
acpi_ex_exit_interpreter();
status = acpi_os_wait_semaphore(semaphore, 1, timeout);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"*** Thread awake after blocking, %s\n",
acpi_format_exception(status)));
/* Reacquire the interpreter */
acpi_ex_enter_interpreter();
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_wait_mutex
*
* PARAMETERS: mutex - Mutex to wait on
* timeout - Max time to wait
*
* RETURN: Status
*
* DESCRIPTION: Implements a mutex wait with a check to see if the
* mutex is available immediately. If it is not, the
* interpreter is released before waiting.
*
******************************************************************************/
acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_system_wait_mutex);
status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT);
if (ACPI_SUCCESS(status)) {
return_ACPI_STATUS(status);
}
if (status == AE_TIME) {
/* We must wait, so unlock the interpreter */
acpi_ex_exit_interpreter();
status = acpi_os_acquire_mutex(mutex, timeout);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"*** Thread awake after blocking, %s\n",
acpi_format_exception(status)));
/* Reacquire the interpreter */
acpi_ex_enter_interpreter();
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_stall
*
* PARAMETERS: how_long - The amount of time to stall,
* in microseconds
*
* RETURN: Status
*
* DESCRIPTION: Suspend running thread for specified amount of time.
* Note: ACPI specification requires that Stall() does not
* relinquish the processor, and delays longer than 100 usec
* should use Sleep() instead. We allow stalls up to 255 usec
* for compatibility with other interpreters and existing BIOSs.
*
******************************************************************************/
acpi_status acpi_ex_system_do_stall(u32 how_long)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_ENTRY();
if (how_long > 255) { /* 255 microseconds */
/*
* Longer than 255 usec, this is an error
*
* (ACPI specifies 100 usec as max, but this gives some slack in
* order to support existing BIOSs)
*/
ACPI_ERROR((AE_INFO, "Time parameter is too large (%u)",
how_long));
status = AE_AML_OPERAND_VALUE;
} else {
acpi_os_stall(how_long);
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_sleep
*
* PARAMETERS: how_long - The amount of time to sleep,
* in milliseconds
*
* RETURN: None
*
* DESCRIPTION: Sleep the running thread for specified amount of time.
*
******************************************************************************/
acpi_status acpi_ex_system_do_sleep(u64 how_long)
{
ACPI_FUNCTION_ENTRY();
/* Since this thread will sleep, we must release the interpreter */
acpi_ex_exit_interpreter();
/*
* For compatibility with other ACPI implementations and to prevent
* accidental deep sleeps, limit the sleep time to something reasonable.
*/
if (how_long > ACPI_MAX_SLEEP) {
how_long = ACPI_MAX_SLEEP;
}
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
acpi_ex_enter_interpreter();
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_signal_event
*
* PARAMETERS: obj_desc - The object descriptor for this op
*
* RETURN: Status
*
* DESCRIPTION: Provides an access point to perform synchronization operations
* within the AML.
*
******************************************************************************/
acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_system_signal_event);
if (obj_desc) {
status =
acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_wait_event
*
* PARAMETERS: time_desc - The 'time to delay' object descriptor
* obj_desc - The object descriptor for this op
*
* RETURN: Status
*
* DESCRIPTION: Provides an access point to perform synchronization operations
* within the AML. This operation is a request to wait for an
* event.
*
******************************************************************************/
acpi_status
acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
union acpi_operand_object *obj_desc)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_system_wait_event);
if (obj_desc) {
status =
acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore,
(u16) time_desc->integer.
value);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_reset_event
*
* PARAMETERS: obj_desc - The object descriptor for this op
*
* RETURN: Status
*
* DESCRIPTION: Reset an event to a known state.
*
******************************************************************************/
acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
{
acpi_status status = AE_OK;
acpi_semaphore temp_semaphore;
ACPI_FUNCTION_ENTRY();
/*
* We are going to simply delete the existing semaphore and
* create a new one!
*/
status =
acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
if (ACPI_SUCCESS(status)) {
(void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore);
obj_desc->event.os_semaphore = temp_semaphore;
}
return (status);
}

View File

@@ -1,438 +0,0 @@
/******************************************************************************
*
* Module Name: exutils - interpreter/scanner utilities
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
/*
* DEFINE_AML_GLOBALS is tested in amlcode.h
* to determine whether certain global names should be "defined" or only
* "declared" in the current compilation. This enhances maintainability
* by enabling a single header file to embody all knowledge of the names
* in question.
*
* Exactly one module of any executable should #define DEFINE_GLOBALS
* before #including the header files which use this convention. The
* names in question will be defined and initialized in that module,
* and declared as extern in all other modules which #include those
* header files.
*/
#define DEFINE_AML_GLOBALS
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exutils")
/* Local prototypes */
static u32 acpi_ex_digits_needed(u64 value, u32 base);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
* FUNCTION: acpi_ex_enter_interpreter
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Enter the interpreter execution region. Failure to enter
* the interpreter region is a fatal system error. Used in
* conjunction with exit_interpreter.
*
******************************************************************************/
void acpi_ex_enter_interpreter(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_enter_interpreter);
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not acquire AML Interpreter mutex"));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_exit_interpreter
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Exit the interpreter execution region. This is the top level
* routine used to exit the interpreter when all processing has
* been completed, or when the method blocks.
*
* Cases where the interpreter is unlocked internally:
* 1) Method will be blocked on a Sleep() AML opcode
* 2) Method will be blocked on an Acquire() AML opcode
* 3) Method will be blocked on a Wait() AML opcode
* 4) Method will be blocked to acquire the global lock
* 5) Method will be blocked waiting to execute a serialized control
* method that is currently executing
* 6) About to invoke a user-installed opregion handler
*
******************************************************************************/
void acpi_ex_exit_interpreter(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_exit_interpreter);
status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not release AML Interpreter mutex"));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_truncate_for32bit_table
*
* PARAMETERS: obj_desc - Object to be truncated
*
* RETURN: TRUE if a truncation was performed, FALSE otherwise.
*
* DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
* 32-bit, as determined by the revision of the DSDT.
*
******************************************************************************/
u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
{
ACPI_FUNCTION_ENTRY();
/*
* Object must be a valid number and we must be executing
* a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
*/
if ((!obj_desc) ||
(ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) ||
(obj_desc->common.type != ACPI_TYPE_INTEGER)) {
return (FALSE);
}
if ((acpi_gbl_integer_byte_width == 4) &&
(obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) {
/*
* We are executing in a 32-bit ACPI table.
* Truncate the value to 32 bits by zeroing out the upper 32-bit field
*/
obj_desc->integer.value &= (u64)ACPI_UINT32_MAX;
return (TRUE);
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_global_lock
*
* PARAMETERS: field_flags - Flags with Lock rule:
* always_lock or never_lock
*
* RETURN: None
*
* DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
* flags specifiy that it is to be obtained before field access.
*
******************************************************************************/
void acpi_ex_acquire_global_lock(u32 field_flags)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
/* Only use the lock if the always_lock bit is set */
if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
return_VOID;
}
/* Attempt to get the global lock, wait forever */
status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER,
acpi_gbl_global_lock_mutex,
acpi_os_get_thread_id());
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not acquire Global Lock"));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_global_lock
*
* PARAMETERS: field_flags - Flags with Lock rule:
* always_lock or never_lock
*
* RETURN: None
*
* DESCRIPTION: Release the ACPI hardware Global Lock
*
******************************************************************************/
void acpi_ex_release_global_lock(u32 field_flags)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ex_release_global_lock);
/* Only use the lock if the always_lock bit is set */
if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) {
return_VOID;
}
/* Release the global lock */
status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
if (ACPI_FAILURE(status)) {
/* Report the error, but there isn't much else we can do */
ACPI_EXCEPTION((AE_INFO, status,
"Could not release Global Lock"));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_digits_needed
*
* PARAMETERS: value - Value to be represented
* base - Base of representation
*
* RETURN: The number of digits.
*
* DESCRIPTION: Calculate the number of digits needed to represent the Value
* in the given Base (Radix)
*
******************************************************************************/
static u32 acpi_ex_digits_needed(u64 value, u32 base)
{
u32 num_digits;
u64 current_value;
ACPI_FUNCTION_TRACE(ex_digits_needed);
/* u64 is unsigned, so we don't worry about a '-' prefix */
if (value == 0) {
return_UINT32(1);
}
current_value = value;
num_digits = 0;
/* Count the digits in the requested base */
while (current_value) {
(void)acpi_ut_short_divide(current_value, base, &current_value,
NULL);
num_digits++;
}
return_UINT32(num_digits);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_eisa_id_to_string
*
* PARAMETERS: compressed_id - EISAID to be converted
* out_string - Where to put the converted string (8 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert a numeric EISAID to string representation. Return
* buffer must be large enough to hold the string. The string
* returned is always exactly of length ACPI_EISAID_STRING_SIZE
* (includes null terminator). The EISAID is always 32 bits.
*
******************************************************************************/
void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id)
{
u32 swapped_id;
ACPI_FUNCTION_ENTRY();
/* The EISAID should be a 32-bit integer */
if (compressed_id > ACPI_UINT32_MAX) {
ACPI_WARNING((AE_INFO,
"Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
ACPI_FORMAT_UINT64(compressed_id)));
}
/* Swap ID to big-endian to get contiguous bits */
swapped_id = acpi_ut_dword_byte_swap((u32)compressed_id);
/* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
out_string[0] =
(char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F));
out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F));
out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F));
out_string[3] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 12);
out_string[4] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 8);
out_string[5] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 4);
out_string[6] = acpi_ut_hex_to_ascii_char((u64) swapped_id, 0);
out_string[7] = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_integer_to_string
*
* PARAMETERS: out_string - Where to put the converted string. At least
* 21 bytes are needed to hold the largest
* possible 64-bit integer.
* value - Value to be converted
*
* RETURN: None, string
*
* DESCRIPTION: Convert a 64-bit integer to decimal string representation.
* Assumes string buffer is large enough to hold the string. The
* largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
*
******************************************************************************/
void acpi_ex_integer_to_string(char *out_string, u64 value)
{
u32 count;
u32 digits_needed;
u32 remainder;
ACPI_FUNCTION_ENTRY();
digits_needed = acpi_ex_digits_needed(value, 10);
out_string[digits_needed] = 0;
for (count = digits_needed; count > 0; count--) {
(void)acpi_ut_short_divide(value, 10, &value, &remainder);
out_string[count - 1] = (char)('0' + remainder);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_cls_to_string
*
* PARAMETERS: out_string - Where to put the converted string (7 bytes)
* PARAMETERS: class_code - PCI class code to be converted (3 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert 3-bytes PCI class code to string representation.
* Return buffer must be large enough to hold the string. The
* string returned is always exactly of length
* ACPI_PCICLS_STRING_SIZE (includes null terminator).
*
******************************************************************************/
void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3])
{
ACPI_FUNCTION_ENTRY();
/* All 3 bytes are hexadecimal */
out_string[0] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 4);
out_string[1] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 0);
out_string[2] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 4);
out_string[3] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 0);
out_string[4] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 4);
out_string[5] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 0);
out_string[6] = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_is_valid_space_id
*
* PARAMETERS: space_id - ID to be validated
*
* RETURN: TRUE if valid/supported ID.
*
* DESCRIPTION: Validate an operation region space_ID.
*
******************************************************************************/
u8 acpi_is_valid_space_id(u8 space_id)
{
if ((space_id >= ACPI_NUM_PREDEFINED_REGIONS) &&
(space_id < ACPI_USER_REGION_BEGIN) &&
(space_id != ACPI_ADR_SPACE_DATA_TABLE) &&
(space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
return (FALSE);
}
return (TRUE);
}
#endif

View File

@@ -1,181 +0,0 @@
/******************************************************************************
*
* Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwacpi")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/******************************************************************************
*
* FUNCTION: acpi_hw_set_mode
*
* PARAMETERS: mode - SYS_MODE_ACPI or SYS_MODE_LEGACY
*
* RETURN: Status
*
* DESCRIPTION: Transitions the system into the requested mode.
*
******************************************************************************/
acpi_status acpi_hw_set_mode(u32 mode)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_set_mode);
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
if (acpi_gbl_reduced_hardware) {
return_ACPI_STATUS(AE_OK);
}
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT.smi_command) {
ACPI_ERROR((AE_INFO,
"No SMI_CMD in FADT, mode transition failed"));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
/*
* ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
* in FADT: If it is zero, enabling or disabling is not supported.
* As old systems may have used zero for mode transition,
* we make sure both the numbers are zero to determine these
* transitions are not supported.
*/
if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) {
ACPI_ERROR((AE_INFO,
"No ACPI mode transition supported in this system "
"(enable/disable both zero)"));
return_ACPI_STATUS(AE_OK);
}
switch (mode) {
case ACPI_SYS_MODE_ACPI:
/* BIOS should have disabled ALL fixed and GP events */
status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT.acpi_enable, 8);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Attempting to enable ACPI mode\n"));
break;
case ACPI_SYS_MODE_LEGACY:
/*
* BIOS should clear all fixed status bits and restore fixed event
* enable bits to default
*/
status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
(u32)acpi_gbl_FADT.acpi_disable, 8);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Attempting to enable Legacy (non-ACPI) mode\n"));
break;
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not write ACPI mode change"));
return_ACPI_STATUS(status);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_mode
*
* PARAMETERS: none
*
* RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
*
* DESCRIPTION: Return current operating state of system. Determined by
* querying the SCI_EN bit.
*
******************************************************************************/
u32 acpi_hw_get_mode(void)
{
acpi_status status;
u32 value;
ACPI_FUNCTION_TRACE(hw_get_mode);
/* If the Hardware Reduced flag is set, machine is always in acpi mode */
if (acpi_gbl_reduced_hardware) {
return_UINT32(ACPI_SYS_MODE_ACPI);
}
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT.smi_command) {
return_UINT32(ACPI_SYS_MODE_ACPI);
}
status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value);
if (ACPI_FAILURE(status)) {
return_UINT32(ACPI_SYS_MODE_LEGACY);
}
if (value) {
return_UINT32(ACPI_SYS_MODE_ACPI);
} else {
return_UINT32(ACPI_SYS_MODE_LEGACY);
}
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,243 +0,0 @@
/******************************************************************************
*
* Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
* extended FADT-V5 sleep registers.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <linux/acpi.h>
#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwesleep")
/*******************************************************************************
*
* FUNCTION: acpi_hw_execute_sleep_method
*
* PARAMETERS: method_pathname - Pathname of method to execute
* integer_argument - Argument to pass to the method
*
* RETURN: None
*
* DESCRIPTION: Execute a sleep/wake related method with one integer argument
* and no return value.
*
******************************************************************************/
void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
{
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status;
ACPI_FUNCTION_TRACE(hw_execute_sleep_method);
/* One argument, integer_argument; No return value expected */
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = (u64)integer_argument;
status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",
method_pathname));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_sleep
*
* PARAMETERS: sleep_state - Which sleep state to enter
*
* RETURN: Status
*
* DESCRIPTION: Enter a system sleep state via the extended FADT sleep
* registers (V5 FADT).
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
acpi_status acpi_hw_extended_sleep(u8 sleep_state)
{
acpi_status status;
u8 sleep_type_value;
u64 sleep_status;
ACPI_FUNCTION_TRACE(hw_extended_sleep);
/* Extended sleep registers must be valid */
if (!acpi_gbl_FADT.sleep_control.address ||
!acpi_gbl_FADT.sleep_status.address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Clear wake status (WAK_STS) */
status =
acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
/* Flush caches, as per ACPI specification */
ACPI_FLUSH_CPU_CACHE();
status = acpi_os_prepare_extended_sleep(sleep_state,
acpi_gbl_sleep_type_a,
acpi_gbl_sleep_type_b);
if (ACPI_SKIP(status))
return_ACPI_STATUS(AE_OK);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
/*
* Set the SLP_TYP and SLP_EN bits.
*
* Note: We only use the first value returned by the \_Sx method
* (acpi_gbl_sleep_type_a) - As per ACPI specification.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"Entering sleep state [S%u]\n", sleep_state));
sleep_type_value =
((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
ACPI_X_SLEEP_TYPE_MASK);
status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
&acpi_gbl_FADT.sleep_control);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Wait for transition back to Working State */
do {
status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_wake_prep
*
* PARAMETERS: sleep_state - Which sleep state we just exited
*
* RETURN: Status
*
* DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
* a sleep. Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
{
acpi_status status;
u8 sleep_type_value;
ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
status = acpi_get_sleep_type_data(ACPI_STATE_S0,
&acpi_gbl_sleep_type_a,
&acpi_gbl_sleep_type_b);
if (ACPI_SUCCESS(status)) {
sleep_type_value =
((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
ACPI_X_SLEEP_TYPE_MASK);
(void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
&acpi_gbl_FADT.sleep_control);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_wake
*
* PARAMETERS: sleep_state - Which sleep state we just exited
*
* RETURN: Status
*
* DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_extended_wake(u8 sleep_state)
{
ACPI_FUNCTION_TRACE(hw_extended_wake);
/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
/* Execute the wake methods */
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
/*
* Some BIOS code assumes that WAK_STS will be cleared on resume
* and use it to determine whether the system is rebooting or
* resuming. Clear WAK_STS for compatibility.
*/
(void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
acpi_gbl_system_awake_and_running = TRUE;
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
return_ACPI_STATUS(AE_OK);
}

View File

@@ -1,535 +0,0 @@
/******************************************************************************
*
* Module Name: hwgpe - Low level GPE enable/disable/clear functions
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
static acpi_status
acpi_hw_gpe_enable_write(u8 enable_mask,
struct acpi_gpe_register_info *gpe_register_info);
/******************************************************************************
*
* FUNCTION: acpi_hw_get_gpe_register_bit
*
* PARAMETERS: gpe_event_info - Info block for the GPE
*
* RETURN: Register mask with a one in the GPE bit position
*
* DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
* correct position for the input GPE.
*
******************************************************************************/
u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
{
return ((u32)1 <<
(gpe_event_info->gpe_number -
gpe_event_info->register_info->base_gpe_number));
}
/******************************************************************************
*
* FUNCTION: acpi_hw_low_set_gpe
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
* action - Enable or disable
*
* RETURN: Status
*
* DESCRIPTION: Enable or disable a single GPE in the parent enable register.
* The enable_mask field of the involved GPE register must be
* updated by the caller if necessary.
*
******************************************************************************/
acpi_status
acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 enable_mask;
u32 register_bit;
ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return (AE_NOT_EXIST);
}
/* Get current value of the enable register that contains this GPE */
status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Set or clear just the bit that corresponds to this GPE */
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
switch (action) {
case ACPI_GPE_CONDITIONAL_ENABLE:
/* Only enable if the corresponding enable_mask bit is set */
if (!(register_bit & gpe_register_info->enable_mask)) {
return (AE_BAD_PARAMETER);
}
/*lint -fallthrough */
case ACPI_GPE_ENABLE:
ACPI_SET_BIT(enable_mask, register_bit);
break;
case ACPI_GPE_DISABLE:
ACPI_CLEAR_BIT(enable_mask, register_bit);
break;
default:
ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
return (AE_BAD_PARAMETER);
}
/* Write the updated enable mask */
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be cleared
*
* RETURN: Status
*
* DESCRIPTION: Clear the status bit for a single GPE.
*
******************************************************************************/
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 register_bit;
ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return (AE_NOT_EXIST);
}
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
status = acpi_hw_write(register_bit,
&gpe_register_info->status_address);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_get_gpe_status
*
* PARAMETERS: gpe_event_info - Info block for the GPE to queried
* event_status - Where the GPE status is returned
*
* RETURN: Status
*
* DESCRIPTION: Return the status of a single GPE.
*
******************************************************************************/
acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
acpi_event_status *event_status)
{
u32 in_byte;
u32 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_event_status local_event_status = 0;
acpi_status status;
ACPI_FUNCTION_ENTRY();
if (!event_status) {
return (AE_BAD_PARAMETER);
}
/* GPE currently handled? */
if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
ACPI_GPE_DISPATCH_NONE) {
local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
}
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
/* Get the register bitmask for this GPE */
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* GPE currently enabled? (enabled for runtime?) */
if (register_bit & gpe_register_info->enable_for_run) {
local_event_status |= ACPI_EVENT_FLAG_ENABLED;
}
/* GPE enabled for wake? */
if (register_bit & gpe_register_info->enable_for_wake) {
local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
}
/* GPE currently enabled (enable bit == 1)? */
status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
if (register_bit & in_byte) {
local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
}
/* GPE currently active (status bit == 1)? */
status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
return (status);
}
if (register_bit & in_byte) {
local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
}
/* Set return value */
(*event_status) = local_event_status;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_gpe_enable_write
*
* PARAMETERS: enable_mask - Bit mask to write to the GPE register
* gpe_register_info - Gpe Register info
*
* RETURN: Status
*
* DESCRIPTION: Write the enable mask byte to the given GPE register.
*
******************************************************************************/
static acpi_status
acpi_hw_gpe_enable_write(u8 enable_mask,
struct acpi_gpe_register_info *gpe_register_info)
{
acpi_status status;
gpe_register_info->enable_mask = enable_mask;
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Disable all GPEs within a single GPE block
*
******************************************************************************/
acpi_status
acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context)
{
u32 i;
acpi_status status;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Disable all GPEs in this register */
status =
acpi_hw_gpe_enable_write(0x00,
&gpe_block->register_info[i]);
if (ACPI_FAILURE(status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Clear status bits for all GPEs within a single GPE block
*
******************************************************************************/
acpi_status
acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block, void *context)
{
u32 i;
acpi_status status;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Clear status on all GPEs in this register */
status =
acpi_hw_write(0xFF,
&gpe_block->register_info[i].status_address);
if (ACPI_FAILURE(status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_runtime_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
* combination wake/run GPEs.
*
******************************************************************************/
acpi_status
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info * gpe_block,
void *context)
{
u32 i;
acpi_status status;
struct acpi_gpe_register_info *gpe_register_info;
/* NOTE: assumes that all GPEs are currently disabled */
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
gpe_register_info = &gpe_block->register_info[i];
if (!gpe_register_info->enable_for_run) {
continue;
}
/* Enable all "runtime" GPEs in this register */
status =
acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run,
gpe_register_info);
if (ACPI_FAILURE(status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_wakeup_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
* combination wake/run GPEs.
*
******************************************************************************/
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context)
{
u32 i;
acpi_status status;
struct acpi_gpe_register_info *gpe_register_info;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
gpe_register_info = &gpe_block->register_info[i];
/*
* Enable all "wake" GPEs in this register and disable the
* remaining ones.
*/
status =
acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
gpe_register_info);
if (ACPI_FAILURE(status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_all_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks
*
******************************************************************************/
acpi_status acpi_hw_disable_all_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_runtime_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
*
******************************************************************************/
acpi_status acpi_hw_enable_all_runtime_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_wakeup_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
*
******************************************************************************/
acpi_status acpi_hw_enable_all_wakeup_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,420 +0,0 @@
/*******************************************************************************
*
* Module Name: hwpci - Obtain PCI bus, device, and function numbers
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("hwpci")
/* PCI configuration space values */
#define PCI_CFG_HEADER_TYPE_REG 0x0E
#define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
#define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
/* PCI header values */
#define PCI_HEADER_TYPE_MASK 0x7F
#define PCI_TYPE_BRIDGE 0x01
#define PCI_TYPE_CARDBUS_BRIDGE 0x02
typedef struct acpi_pci_device {
acpi_handle device;
struct acpi_pci_device *next;
} acpi_pci_device;
/* Local prototypes */
static acpi_status
acpi_hw_build_pci_list(acpi_handle root_pci_device,
acpi_handle pci_region,
struct acpi_pci_device **return_list_head);
static acpi_status
acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
struct acpi_pci_device *list_head);
static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
static acpi_status
acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
acpi_handle pci_device,
u16 *bus_number, u8 *is_bridge);
/*******************************************************************************
*
* FUNCTION: acpi_hw_derive_pci_id
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* root_pci_device - A handle to a PCI device object. This
* object must be a PCI Root Bridge having a
* _HID value of either PNP0A03 or PNP0A08
* pci_region - A handle to a PCI configuration space
* Operation Region being initialized
*
* RETURN: Status
*
* DESCRIPTION: This function derives a full PCI ID for a PCI device,
* consisting of a Segment number, Bus number, Device number,
* and function code.
*
* The PCI hardware dynamically configures PCI bus numbers
* depending on the bus topology discovered during system
* initialization. This function is invoked during configuration
* of a PCI_Config Operation Region in order to (possibly) update
* the Bus/Device/Function numbers in the pci_id with the actual
* values as determined by the hardware and operating system
* configuration.
*
* The pci_id parameter is initially populated during the Operation
* Region initialization. This function is then called, and is
* will make any necessary modifications to the Bus, Device, or
* Function number PCI ID subfields as appropriate for the
* current hardware and OS configuration.
*
* NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
* interface since this feature is OS-independent. This module
* specifically avoids any use of recursion by building a local
* temporary device list.
*
******************************************************************************/
acpi_status
acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
acpi_handle root_pci_device, acpi_handle pci_region)
{
acpi_status status;
struct acpi_pci_device *list_head;
ACPI_FUNCTION_TRACE(hw_derive_pci_id);
if (!pci_id) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Build a list of PCI devices, from pci_region up to root_pci_device */
status =
acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
if (ACPI_SUCCESS(status)) {
/* Walk the list, updating the PCI device/function/bus numbers */
status = acpi_hw_process_pci_list(pci_id, list_head);
/* Delete the list */
acpi_hw_delete_pci_list(list_head);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_build_pci_list
*
* PARAMETERS: root_pci_device - A handle to a PCI device object. This
* object is guaranteed to be a PCI Root
* Bridge having a _HID value of either
* PNP0A03 or PNP0A08
* pci_region - A handle to the PCI configuration space
* Operation Region
* return_list_head - Where the PCI device list is returned
*
* RETURN: Status
*
* DESCRIPTION: Builds a list of devices from the input PCI region up to the
* Root PCI device for this namespace subtree.
*
******************************************************************************/
static acpi_status
acpi_hw_build_pci_list(acpi_handle root_pci_device,
acpi_handle pci_region,
struct acpi_pci_device **return_list_head)
{
acpi_handle current_device;
acpi_handle parent_device;
acpi_status status;
struct acpi_pci_device *list_element;
/*
* Ascend namespace branch until the root_pci_device is reached, building
* a list of device nodes. Loop will exit when either the PCI device is
* found, or the root of the namespace is reached.
*/
*return_list_head = NULL;
current_device = pci_region;
while (1) {
status = acpi_get_parent(current_device, &parent_device);
if (ACPI_FAILURE(status)) {
/* Must delete the list before exit */
acpi_hw_delete_pci_list(*return_list_head);
return (status);
}
/* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
if (parent_device == root_pci_device) {
return (AE_OK);
}
list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
if (!list_element) {
/* Must delete the list before exit */
acpi_hw_delete_pci_list(*return_list_head);
return (AE_NO_MEMORY);
}
/* Put new element at the head of the list */
list_element->next = *return_list_head;
list_element->device = parent_device;
*return_list_head = list_element;
current_device = parent_device;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_process_pci_list
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* list_head - Device list created by
* acpi_hw_build_pci_list
*
* RETURN: Status
*
* DESCRIPTION: Walk downward through the PCI device list, getting the device
* info for each, via the PCI configuration space and updating
* the PCI ID as necessary. Deletes the list during traversal.
*
******************************************************************************/
static acpi_status
acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
struct acpi_pci_device *list_head)
{
acpi_status status = AE_OK;
struct acpi_pci_device *info;
u16 bus_number;
u8 is_bridge = TRUE;
ACPI_FUNCTION_NAME(hw_process_pci_list);
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function));
bus_number = pci_id->bus;
/*
* Descend down the namespace tree, collecting PCI device, function,
* and bus numbers. bus_number is only important for PCI bridges.
* Algorithm: As we descend the tree, use the last valid PCI device,
* function, and bus numbers that are discovered, and assign them
* to the PCI ID for the target device.
*/
info = list_head;
while (info) {
status = acpi_hw_get_pci_device_info(pci_id, info->device,
&bus_number, &is_bridge);
if (ACPI_FAILURE(status)) {
return (status);
}
info = info->next;
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
"Status %X BusNumber %X IsBridge %X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function, status, bus_number, is_bridge));
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_delete_pci_list
*
* PARAMETERS: list_head - Device list created by
* acpi_hw_build_pci_list
*
* RETURN: None
*
* DESCRIPTION: Free the entire PCI list.
*
******************************************************************************/
static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
{
struct acpi_pci_device *next;
struct acpi_pci_device *previous;
next = list_head;
while (next) {
previous = next;
next = previous->next;
ACPI_FREE(previous);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_pci_device_info
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* pci_device - Handle for the PCI device object
* bus_number - Where a PCI bridge bus number is returned
* is_bridge - Return value, indicates if this PCI
* device is a PCI bridge
*
* RETURN: Status
*
* DESCRIPTION: Get the device info for a single PCI device object. Get the
* _ADR (contains PCI device and function numbers), and for PCI
* bridge devices, get the bus number from PCI configuration
* space.
*
******************************************************************************/
static acpi_status
acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
acpi_handle pci_device,
u16 *bus_number, u8 *is_bridge)
{
acpi_status status;
acpi_object_type object_type;
u64 return_value;
u64 pci_value;
/* We only care about objects of type Device */
status = acpi_get_type(pci_device, &object_type);
if (ACPI_FAILURE(status)) {
return (status);
}
if (object_type != ACPI_TYPE_DEVICE) {
return (AE_OK);
}
/* We need an _ADR. Ignore device if not present */
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
pci_device, &return_value);
if (ACPI_FAILURE(status)) {
return (AE_OK);
}
/*
* From _ADR, get the PCI Device and Function and
* update the PCI ID.
*/
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
/*
* If the previous device was a bridge, use the previous
* device bus number
*/
if (*is_bridge) {
pci_id->bus = *bus_number;
}
/*
* Get the bus numbers from PCI Config space:
*
* First, get the PCI header_type
*/
*is_bridge = FALSE;
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_HEADER_TYPE_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
/* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
pci_value &= PCI_HEADER_TYPE_MASK;
if ((pci_value != PCI_TYPE_BRIDGE) &&
(pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
return (AE_OK);
}
/* Bridge: Get the Primary bus_number */
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_PRIMARY_BUS_NUMBER_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
*is_bridge = TRUE;
pci_id->bus = (u16)pci_value;
/* Bridge: Get the Secondary bus_number */
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_SECONDARY_BUS_NUMBER_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
*bus_number = (u16)pci_value;
return (AE_OK);
}

View File

@@ -1,668 +0,0 @@
/*******************************************************************************
*
* Module Name: hwregs - Read/write access functions for the various ACPI
* control and status registers.
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acevents.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwregs")
#if (!ACPI_REDUCED_HARDWARE)
/* Local Prototypes */
static acpi_status
acpi_hw_read_multiple(u32 *value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b);
static acpi_status
acpi_hw_write_multiple(u32 value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b);
#endif /* !ACPI_REDUCED_HARDWARE */
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_register
*
* PARAMETERS: reg - GAS register structure
* max_bit_width - Max bit_width supported (32 or 64)
* address - Pointer to where the gas->address
* is returned
*
* RETURN: Status
*
* DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
* pointer, Address, space_id, bit_width, and bit_offset.
*
******************************************************************************/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address)
{
/* Must have a valid pointer to a GAS structure */
if (!reg) {
return (AE_BAD_PARAMETER);
}
/*
* Copy the target address. This handles possible alignment issues.
* Address must not be null. A null address also indicates an optional
* ACPI register that is not supported, so no error message.
*/
ACPI_MOVE_64_TO_64(address, &reg->address);
if (!(*address)) {
return (AE_BAD_ADDRESS);
}
/* Validate the space_ID */
if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
ACPI_ERROR((AE_INFO,
"Unsupported address space: 0x%X", reg->space_id));
return (AE_SUPPORT);
}
/* Validate the bit_width */
if ((reg->bit_width != 8) &&
(reg->bit_width != 16) &&
(reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
ACPI_ERROR((AE_INFO,
"Unsupported register bit width: 0x%X",
reg->bit_width));
return (AE_SUPPORT);
}
/* Validate the bit_offset. Just a warning for now. */
if (reg->bit_offset != 0) {
ACPI_WARNING((AE_INFO,
"Unsupported register bit offset: 0x%X",
reg->bit_offset));
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_read
*
* PARAMETERS: value - Where the value is returned
* reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
* version of acpi_read, used internally since the overhead of
* 64-bit values is not needed.
*
* LIMITATIONS: <These limitations also apply to acpi_hw_write>
* bit_width must be exactly 8, 16, or 32.
* space_ID must be system_memory or system_IO.
* bit_offset and access_width are currently ignored, as there has
* not been a need to implement these.
*
******************************************************************************/
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
u64 address;
u64 value64;
acpi_status status;
ACPI_FUNCTION_NAME(hw_read);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Initialize entire 32-bit return value to zero */
*value = 0;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, &value64, reg->bit_width);
*value = (u32)value64;
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_read_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_write
*
* PARAMETERS: value - Value to be written
* reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
* version of acpi_write, used internally since the overhead of
* 64-bit values is not needed.
*
******************************************************************************/
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(hw_write);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, (u64)value,
reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_write_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_hw_clear_acpi_status
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Clears all fixed and general purpose status bits
*
******************************************************************************/
acpi_status acpi_hw_clear_acpi_status(void)
{
acpi_status status;
acpi_cpu_flags lock_flags = 0;
ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
ACPI_BITMASK_ALL_FIXED_STATUS,
ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
/* Clear the fixed events in PM1 A/B */
status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
ACPI_BITMASK_ALL_FIXED_STATUS);
acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Clear the GPE Bits in all GPE registers in all GPE blocks */
status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
exit:
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_bit_register_info
*
* PARAMETERS: register_id - Index of ACPI Register to access
*
* RETURN: The bitmask to be used when accessing the register
*
* DESCRIPTION: Map register_id into a register bitmask.
*
******************************************************************************/
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
{
ACPI_FUNCTION_ENTRY();
if (register_id > ACPI_BITREG_MAX) {
ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: 0x%X",
register_id));
return (NULL);
}
return (&acpi_gbl_bit_register_info[register_id]);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_write_pm1_control
*
* PARAMETERS: pm1a_control - Value to be written to PM1A control
* pm1b_control - Value to be written to PM1B control
*
* RETURN: Status
*
* DESCRIPTION: Write the PM1 A/B control registers. These registers are
* different than than the PM1 A/B status and enable registers
* in that different values can be written to the A/B registers.
* Most notably, the SLP_TYP bits can be different, as per the
* values returned from the _Sx predefined methods.
*
******************************************************************************/
acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_write_pm1_control);
status =
acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (acpi_gbl_FADT.xpm1b_control_block.address) {
status =
acpi_hw_write(pm1b_control,
&acpi_gbl_FADT.xpm1b_control_block);
}
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_register_read
*
* PARAMETERS: register_id - ACPI Register ID
* return_value - Where the register value is returned
*
* RETURN: Status and the value read.
*
* DESCRIPTION: Read from the specified ACPI register
*
******************************************************************************/
acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
{
u32 value = 0;
acpi_status status;
ACPI_FUNCTION_TRACE(hw_register_read);
switch (register_id) {
case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
status = acpi_hw_read_multiple(&value,
&acpi_gbl_xpm1a_status,
&acpi_gbl_xpm1b_status);
break;
case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
status = acpi_hw_read_multiple(&value,
&acpi_gbl_xpm1a_enable,
&acpi_gbl_xpm1b_enable);
break;
case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
status = acpi_hw_read_multiple(&value,
&acpi_gbl_FADT.
xpm1a_control_block,
&acpi_gbl_FADT.
xpm1b_control_block);
/*
* Zero the write-only bits. From the ACPI specification, "Hardware
* Write-Only Bits": "Upon reads to registers with write-only bits,
* software masks out all write-only bits."
*/
value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
break;
case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
status =
acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
status =
acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8);
break;
default:
ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
status = AE_BAD_PARAMETER;
break;
}
if (ACPI_SUCCESS(status)) {
*return_value = value;
}
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_register_write
*
* PARAMETERS: register_id - ACPI Register ID
* value - The value to write
*
* RETURN: Status
*
* DESCRIPTION: Write to the specified ACPI register
*
* NOTE: In accordance with the ACPI specification, this function automatically
* preserves the value of the following bits, meaning that these bits cannot be
* changed via this interface:
*
* PM1_CONTROL[0] = SCI_EN
* PM1_CONTROL[9]
* PM1_STATUS[11]
*
* ACPI References:
* 1) Hardware Ignored Bits: When software writes to a register with ignored
* bit fields, it preserves the ignored bit fields
* 2) SCI_EN: OSPM always preserves this bit position
*
******************************************************************************/
acpi_status acpi_hw_register_write(u32 register_id, u32 value)
{
acpi_status status;
u32 read_value;
ACPI_FUNCTION_TRACE(hw_register_write);
switch (register_id) {
case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
/*
* Handle the "ignored" bit in PM1 Status. According to the ACPI
* specification, ignored bits are to be preserved when writing.
* Normally, this would mean a read/modify/write sequence. However,
* preserving a bit in the status register is different. Writing a
* one clears the status, and writing a zero preserves the status.
* Therefore, we must always write zero to the ignored bit.
*
* This behavior is clarified in the ACPI 4.0 specification.
*/
value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
status = acpi_hw_write_multiple(value,
&acpi_gbl_xpm1a_status,
&acpi_gbl_xpm1b_status);
break;
case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
status = acpi_hw_write_multiple(value,
&acpi_gbl_xpm1a_enable,
&acpi_gbl_xpm1b_enable);
break;
case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
/*
* Perform a read first to preserve certain bits (per ACPI spec)
* Note: This includes SCI_EN, we never want to change this bit
*/
status = acpi_hw_read_multiple(&read_value,
&acpi_gbl_FADT.
xpm1a_control_block,
&acpi_gbl_FADT.
xpm1b_control_block);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Insert the bits to be preserved */
ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
read_value);
/* Now we can write the data */
status = acpi_hw_write_multiple(value,
&acpi_gbl_FADT.
xpm1a_control_block,
&acpi_gbl_FADT.
xpm1b_control_block);
break;
case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
/*
* For control registers, all reserved bits must be preserved,
* as per the ACPI spec.
*/
status =
acpi_hw_read(&read_value,
&acpi_gbl_FADT.xpm2_control_block);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Insert the bits to be preserved */
ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
read_value);
status =
acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
/* SMI_CMD is currently always in IO space */
status =
acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8);
break;
default:
ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
status = AE_BAD_PARAMETER;
break;
}
exit:
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_read_multiple
*
* PARAMETERS: value - Where the register value is returned
* register_a - First ACPI register (required)
* register_b - Second ACPI register (optional)
*
* RETURN: Status
*
* DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
*
******************************************************************************/
static acpi_status
acpi_hw_read_multiple(u32 *value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b)
{
u32 value_a = 0;
u32 value_b = 0;
acpi_status status;
/* The first register is always required */
status = acpi_hw_read(&value_a, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Second register is optional */
if (register_b->address) {
status = acpi_hw_read(&value_b, register_b);
if (ACPI_FAILURE(status)) {
return (status);
}
}
/*
* OR the two return values together. No shifting or masking is necessary,
* because of how the PM1 registers are defined in the ACPI specification:
*
* "Although the bits can be split between the two register blocks (each
* register block has a unique pointer within the FADT), the bit positions
* are maintained. The register block with unimplemented bits (that is,
* those implemented in the other register block) always returns zeros,
* and writes have no side effects"
*/
*value = (value_a | value_b);
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_write_multiple
*
* PARAMETERS: value - The value to write
* register_a - First ACPI register (required)
* register_b - Second ACPI register (optional)
*
* RETURN: Status
*
* DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
*
******************************************************************************/
static acpi_status
acpi_hw_write_multiple(u32 value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b)
{
acpi_status status;
/* The first register is always required */
status = acpi_hw_write(value, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* Second register is optional
*
* No bit shifting or clearing is necessary, because of how the PM1
* registers are defined in the ACPI specification:
*
* "Although the bits can be split between the two register blocks (each
* register block has a unique pointer within the FADT), the bit positions
* are maintained. The register block with unimplemented bits (that is,
* those implemented in the other register block) always returns zeros,
* and writes have no side effects"
*/
if (register_b->address) {
status = acpi_hw_write(value, register_b);
}
return (status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View File

@@ -1,345 +0,0 @@
/******************************************************************************
*
* Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
* original/legacy sleep/PM registers.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <linux/acpi.h>
#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_hw_legacy_sleep
*
* PARAMETERS: sleep_state - Which sleep state to enter
*
* RETURN: Status
*
* DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
{
struct acpi_bit_register_info *sleep_type_reg_info;
struct acpi_bit_register_info *sleep_enable_reg_info;
u32 pm1a_control;
u32 pm1b_control;
u32 in_value;
acpi_status status;
ACPI_FUNCTION_TRACE(hw_legacy_sleep);
sleep_type_reg_info =
acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
sleep_enable_reg_info =
acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Clear wake status */
status =
acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Clear all fixed and general purpose status bits */
status = acpi_hw_clear_acpi_status();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_disable_all_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get current value of PM1A control */
status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
&pm1a_control);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"Entering sleep state [S%u]\n", sleep_state));
/* Clear the SLP_EN and SLP_TYP fields */
pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
sleep_enable_reg_info->access_bit_mask);
pm1b_control = pm1a_control;
/* Insert the SLP_TYP bits */
pm1a_control |=
(acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
pm1b_control |=
(acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
/*
* We split the writes of SLP_TYP and SLP_EN to workaround
* poorly implemented hardware.
*/
/* Write #1: write the SLP_TYP data to the PM1 Control registers */
status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Insert the sleep enable (SLP_EN) bit */
pm1a_control |= sleep_enable_reg_info->access_bit_mask;
pm1b_control |= sleep_enable_reg_info->access_bit_mask;
/* Flush caches, as per ACPI specification */
ACPI_FLUSH_CPU_CACHE();
status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
pm1b_control);
if (ACPI_SKIP(status))
return_ACPI_STATUS(AE_OK);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
/* Write #2: Write both SLP_TYP + SLP_EN */
status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (sleep_state > ACPI_STATE_S3) {
/*
* We wanted to sleep > S3, but it didn't happen (by virtue of the
* fact that we are still executing!)
*
* Wait ten seconds, then try again. This is to get S4/S5 to work on
* all machines.
*
* We wait so long to allow chipsets that poll this reg very slowly
* to still read the right value. Ideally, this block would go
* away entirely.
*/
acpi_os_stall(10 * ACPI_USEC_PER_SEC);
status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
sleep_enable_reg_info->
access_bit_mask);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Wait for transition back to Working State */
do {
status =
acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} while (!in_value);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_legacy_wake_prep
*
* PARAMETERS: sleep_state - Which sleep state we just exited
*
* RETURN: Status
*
* DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
* sleep.
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
{
acpi_status status;
struct acpi_bit_register_info *sleep_type_reg_info;
struct acpi_bit_register_info *sleep_enable_reg_info;
u32 pm1a_control;
u32 pm1b_control;
ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
/*
* Set SLP_TYPE and SLP_EN to state S0.
* This is unclear from the ACPI Spec, but it is required
* by some machines.
*/
status = acpi_get_sleep_type_data(ACPI_STATE_S0,
&acpi_gbl_sleep_type_a,
&acpi_gbl_sleep_type_b);
if (ACPI_SUCCESS(status)) {
sleep_type_reg_info =
acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
sleep_enable_reg_info =
acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Get current value of PM1A control */
status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
&pm1a_control);
if (ACPI_SUCCESS(status)) {
/* Clear the SLP_EN and SLP_TYP fields */
pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
sleep_enable_reg_info->
access_bit_mask);
pm1b_control = pm1a_control;
/* Insert the SLP_TYP bits */
pm1a_control |= (acpi_gbl_sleep_type_a <<
sleep_type_reg_info->bit_position);
pm1b_control |= (acpi_gbl_sleep_type_b <<
sleep_type_reg_info->bit_position);
/* Write the control registers and ignore any errors */
(void)acpi_hw_write_pm1_control(pm1a_control,
pm1b_control);
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_legacy_wake
*
* PARAMETERS: sleep_state - Which sleep state we just exited
*
* RETURN: Status
*
* DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_legacy_wake(u8 sleep_state)
{
acpi_status status;
ACPI_FUNCTION_TRACE(hw_legacy_wake);
/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
/*
* GPEs must be enabled before _WAK is called as GPEs
* might get fired there
*
* Restore the GPEs:
* 1) Disable/Clear all GPEs
* 2) Enable all runtime GPEs
*/
status = acpi_hw_disable_all_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_enable_all_runtime_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Now we can execute _WAK, etc. Some machines require that the GPEs
* are enabled before the wake methods are executed.
*/
acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
/*
* Some BIOS code assumes that WAK_STS will be cleared on resume
* and use it to determine whether the system is rebooting or
* resuming. Clear WAK_STS for compatibility.
*/
(void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
ACPI_CLEAR_STATUS);
acpi_gbl_system_awake_and_running = TRUE;
/* Enable power button */
(void)
acpi_write_bit_register(acpi_gbl_fixed_event_info
[ACPI_EVENT_POWER_BUTTON].
enable_register_id, ACPI_ENABLE_EVENT);
(void)
acpi_write_bit_register(acpi_gbl_fixed_event_info
[ACPI_EVENT_POWER_BUTTON].
status_register_id, ACPI_CLEAR_STATUS);
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

Some files were not shown because too many files have changed in this diff Show More