ACPI material for v4.7-rc1

- In-kernel ACPICA code update to the upstream release 20160422
    adding support for ACPI 6.1 along with some previously missing
    bits of ACPI 6.0 support, making a fair amount of fixes and
    cleanups and reducing divergences between the upstream ACPICA
    and the in-kernel code (Bob Moore, Lv Zheng, Al Stone, Aleksey
    Makarov, Will Miles).
 
  - ACPI Generic Event Device (GED) support and a fix for it (Sinan Kaya,
    Paul Gortmaker).
 
  - INT3406 thermal driver for display thermal management and ACPI
    backlight support code reorganization related to it (Aaron Lu,
    Arnd Bergmann).
 
  - Support for exporting the value returned by the _HRV (hardware
    revision) ACPI object via sysfs (Betty Dall).
 
  - Removal of the EXPERT dependency for ACPI on ARM64 (Mark Brown).
 
  - Rework of the handling of ACPI _OSI mechanism allowing the
    _OSI("Darwin") support to be overridden from the kernel command
    line among other things (Lv Zheng, Chen Yu).
 
  - Rework of the ACPI tables override mechanism to prepare it for
    the introduction of overlays support going forward (Lv Zheng,
    Rafael Wysocki).
 
  - Fixes related to the ECDT support and module-level execution
    of AML (Lv Zheng).
 
  - ACPI PCI interrupts management update to make it work better on
    ARM64 mostly (Sinan Kaya).
 
  - ACPI SRAT handling update to make the code process all entires
    in the table order regardless of the entry type (Lukasz Anaczkowski).
 
  - EFI power off support for full-hardware ACPI platforms that don't
    support ACPI S5 (Chen Yu).
 
  - Fixes and cleanups related to the ACPI core's sysfs interface
    (Dan Carpenter, Betty Dall).
 
  - acpi_dev_present() API rework to reduce possible confusion related
    to it (Lukas Wunner).
 
  - Removal of CLK_IS_ROOT from two ACPI drivers (Stephen Boyd).
 
 /
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCAAGBQJXOjM+AAoJEILEb/54YlRxNO4P/0FsajR2iXfHybiHyJq+Iddk
 MX+Jealb5klnXXtuih90oOHft9NypV1ESO7bcmjSz+2tuSgoXifdI3GO0aFghj7v
 h8SaVpCGzlm+u8y+Ppbxk+eWHAV1+ohV8uaO47yDUjuyZgG6c702QqrJVaqunQoq
 KQd+kqK5bhcaLhrx9Ro0I4Jbz0TdFa8j7noUTRXtDfJ9V4xZ3a6QfXz3H6GU4L31
 kNKjroxkFXpHMj2mYXuskqw2IWoRZw7Z7kpLv0dM44nko6c+oM8/9BIx4xh1IbR4
 vvgn/C2QYe45fz4Or/qmrPzGZ/kQtLiiVC2B/GWbCTezu3Px9E3V2NI0xLktVe0g
 Y/MsRdzMs0TInWSVezOlTONmfcqZgPhbSmsuI9PJ7izxmzOLVk6tjXARkzWe2gQ0
 N/nOd7I8AMsTMdpBCvf6xjJXqHRl6jdXuHAIhcPC5DINQ0daz8FZ4Cw42MtVKo0I
 2OiZ7ZnAnDDHrptV9VwtEvo60Uw/QG8EhdMWyQVaFWe1pFNM9nQtD0P2QeMWUHhZ
 YL7Q63nM8flQIywcSj7jyMWroWZMOI/cFOLGxZjz+yXA3fRizl4J22kJ392gSQti
 da1X8OBKsOvYQutkeGeQCNYWp4j5uKpoMoR4iR4dOLNqguWxaicDSZgsU8cAAk0k
 W+lRS/E8l+we5rxEZYOd
 =rAwm
 -----END PGP SIGNATURE-----

Merge tag 'acpi-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI updates from Rafael Wysocki:
 "The new features here are ACPI 6.1 support (and some previously
  missing bits of ACPI 6.0 support) in ACPICA and two new drivers, a
  driver for the ACPI Generic Event Device (GED) feature introduced by
  ACPI 6.1 and the INT3406 thermal driver for display thermal
  management.  Also the value returned by the _HRV (hardware revision)
  ACPI object will be exported to user space via sysfs now.

  In addition to that, ACPI on ARM64 will not depend on EXPERT any more.

  The rest is mostly fixes and cleanups and some code reorganization.

  Specifics:

   - In-kernel ACPICA code update to the upstream release 20160422
     adding support for ACPI 6.1 along with some previously missing bits
     of ACPI 6.0 support, making a fair amount of fixes and cleanups and
     reducing divergences between the upstream ACPICA and the in-kernel
     code (Bob Moore, Lv Zheng, Al Stone, Aleksey Makarov, Will Miles)

   - ACPI Generic Event Device (GED) support and a fix for it (Sinan
     Kaya, Paul Gortmaker)

   - INT3406 thermal driver for display thermal management and ACPI
     backlight support code reorganization related to it (Aaron Lu, Arnd
     Bergmann)

   - Support for exporting the value returned by the _HRV (hardware
     revision) ACPI object via sysfs (Betty Dall)

   - Removal of the EXPERT dependency for ACPI on ARM64 (Mark Brown)

   - Rework of the handling of ACPI _OSI mechanism allowing the
     _OSI("Darwin") support to be overridden from the kernel command
     line among other things (Lv Zheng, Chen Yu)

   - Rework of the ACPI tables override mechanism to prepare it for the
     introduction of overlays support going forward (Lv Zheng, Rafael
     Wysocki)

   - Fixes related to the ECDT support and module-level execution of AML
     (Lv Zheng)

   - ACPI PCI interrupts management update to make it work better on
     ARM64 mostly (Sinan Kaya)

   - ACPI SRAT handling update to make the code process all entires in
     the table order regardless of the entry type (Lukasz Anaczkowski)

   - EFI power off support for full-hardware ACPI platforms that don't
     support ACPI S5 (Chen Yu)

   - Fixes and cleanups related to the ACPI core's sysfs interface (Dan
     Carpenter, Betty Dall)

   - acpi_dev_present() API rework to reduce possible confusion related
     to it (Lukas Wunner)

   - Removal of CLK_IS_ROOT from two ACPI drivers (Stephen Boyd)"

* tag 'acpi-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (82 commits)
  ACPI / video: mark acpi_video_get_levels() inline
  Thermal / ACPI / video: add INT3406 thermal driver
  ACPI / GED: make evged.c explicitly non-modular
  ACPI / tables: Fix DSDT override mechanism
  ACPI / sysfs: fix error code in get_status()
  ACPICA: Update version to 20160422
  ACPICA: Move all ASCII utilities to a common file
  ACPICA: ACPI 2.0, Hardware: Add access_width/bit_offset support for acpi_hw_write()
  ACPICA: ACPI 2.0, Hardware: Add access_width/bit_offset support in acpi_hw_read()
  ACPICA: Executer: Introduce a set of macros to handle bit width mask generation
  ACPICA: Hardware: Add optimized access bit width support
  ACPICA: Utilities: Add ACPI_IS_ALIGNED() macro
  ACPICA: Renamed some #defined flag constants for clarity
  ACPICA: ACPI 6.0, tools/iasl: Add support for new resource descriptors
  ACPICA: ACPI 6.0: Update _BIX support for new package element
  ACPICA: ACPI 6.1: Support for new PCCT subtable
  ACPICA: Refactor evaluate_object to reduce nesting
  ACPICA: Divergence: remove unwanted spaces for typedef
  ACPI,PCI,IRQ: remove SCI penalize function
  ACPI,PCI,IRQ: remove redundant code in acpi_irq_penalty_init()
  ..
This commit is contained in:
Linus Torvalds 2016-05-16 19:41:41 -07:00
commit 46c1345062
172 changed files with 3675 additions and 2399 deletions

View File

@ -1,5 +1,5 @@
Overriding ACPI tables via initrd
=================================
Upgrading ACPI tables via initrd
================================
1) Introduction (What is this about)
2) What is this for
@ -9,12 +9,14 @@ Overriding ACPI tables via initrd
1) What is this about
---------------------
If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
override nearly any ACPI table provided by the BIOS with an instrumented,
modified one.
If the ACPI_TABLE_UPGRADE compile option is true, it is possible to
upgrade the ACPI execution environment that is defined by the ACPI tables
via upgrading the ACPI tables provided by the BIOS with an instrumented,
modified, more recent version one, or installing brand new ACPI tables.
For a full list of ACPI tables that can be overridden, take a look at
the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
For a full list of ACPI tables that can be upgraded/installed, take a look
at the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in
drivers/acpi/tables.c.
All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
be overridable, except:
- ACPI_SIG_RSDP (has a signature of 6 bytes)
@ -25,17 +27,20 @@ Both could get implemented as well.
2) What is this for
-------------------
Please keep in mind that this is a debug option.
ACPI tables should not get overridden for productive use.
If BIOS ACPI tables are overridden the kernel will get tainted with the
TAINT_OVERRIDDEN_ACPI_TABLE flag.
Complain to your platform/BIOS vendor if you find a bug which is so sever
that a workaround is not accepted in the Linux kernel.
Complain to your platform/BIOS vendor if you find a bug which is so severe
that a workaround is not accepted in the Linux kernel. And this facility
allows you to upgrade the buggy tables before your platform/BIOS vendor
releases an upgraded BIOS binary.
Still, it can and should be enabled in any kernel, because:
- There is no functional change with not instrumented initrds
- It provides a powerful feature to easily debug and test ACPI BIOS table
compatibility with the Linux kernel.
This facility can be used by platform/BIOS vendors to provide a Linux
compatible environment without modifying the underlying platform firmware.
This facility also provides a powerful feature to easily debug and test
ACPI BIOS table compatibility with the Linux kernel by modifying old
platform provided ACPI tables or inserting new ACPI tables.
It can and should be enabled in any kernel because there is no functional
change with not instrumented initrds.
3) How does it work
@ -50,23 +55,31 @@ iasl -d *.dat
# For example add this statement into a _PRT (PCI Routing Table) function
# of the DSDT:
Store("HELLO WORLD", debug)
# And increase the OEM Revision. For example, before modification:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)
# After modification:
DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)
iasl -sa dsdt.dsl
# Add the raw ACPI tables to an uncompressed cpio archive.
# They must be put into a /kernel/firmware/acpi directory inside the
# cpio archive.
# The uncompressed cpio archive must be the first.
# Other, typically compressed cpio archives, must be
# concatenated on top of the uncompressed one.
# They must be put into a /kernel/firmware/acpi directory inside the cpio
# archive. Note that if the table put here matches a platform table
# (similar Table Signature, and similar OEMID, and similar OEM Table ID)
# with a more recent OEM Revision, the platform table will be upgraded by
# this table. If the table put here doesn't match a platform table
# (dissimilar Table Signature, or dissimilar OEMID, or dissimilar OEM Table
# ID), this table will be appended.
mkdir -p kernel/firmware/acpi
cp dsdt.aml kernel/firmware/acpi
# A maximum of: #define ACPI_OVERRIDE_TABLES 10
# tables are currently allowed (see osl.c):
# A maximum of "NR_ACPI_INITRD_TABLES (64)" tables are currently allowed
# (see osl.c):
iasl -sa facp.dsl
iasl -sa ssdt1.dsl
cp facp.aml kernel/firmware/acpi
cp ssdt1.aml kernel/firmware/acpi
# Create the uncompressed cpio archive and concatenate the original initrd
# on top:
# The uncompressed cpio archive must be the first. Other, typically
# compressed cpio archives, must be concatenated on top of the uncompressed
# one. Following command creates the uncompressed cpio archive and
# concatenates the original initrd on top:
find kernel | cpio -H newc --create > /boot/instrumented_initrd
cat /boot/initrd >>/boot/instrumented_initrd
# reboot with increased acpi debug level, e.g. boot params:

View File

@ -315,6 +315,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
acpi_osi=!* # remove all strings
acpi_osi=! # disable all built-in OS vendor
strings
acpi_osi=!! # enable all built-in OS vendor
strings
acpi_osi= # disable all strings
'acpi_osi=!' can be used in combination with single or

View File

@ -264,6 +264,7 @@ CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_XGENE=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ACPI=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_FANOTIFY=y

View File

@ -445,7 +445,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
/*
* stash over-ride to indicate we've been here

View File

@ -398,6 +398,11 @@ static void __init reserve_initrd(void)
memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
}
static void __init early_initrd_acpi_init(void)
{
early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
}
#else
static void __init early_reserve_initrd(void)
{
@ -405,6 +410,9 @@ static void __init early_reserve_initrd(void)
static void __init reserve_initrd(void)
{
}
static void __init early_initrd_acpi_init(void)
{
}
#endif /* CONFIG_BLK_DEV_INITRD */
static void __init parse_setup_data(void)
@ -1138,9 +1146,7 @@ void __init setup_arch(char **cmdline_p)
reserve_initrd();
#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
#endif
early_initrd_acpi_init();
vsmp_init();

View File

@ -396,7 +396,6 @@ int __init pci_acpi_init(void)
return -ENODEV;
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
acpi_irq_penalty_init();
pcibios_enable_irq = acpi_pci_irq_enable;
pcibios_disable_irq = acpi_pci_irq_disable;
x86_init.pci.init_irq = x86_init_noop;

View File

@ -371,5 +371,5 @@ bool efi_reboot_required(void)
bool efi_poweroff_required(void)
{
return !!acpi_gbl_reduced_hardware;
return acpi_gbl_reduced_hardware || acpi_no_s5;
}

View File

@ -5,10 +5,10 @@
menuconfig ACPI
bool "ACPI (Advanced Configuration and Power Interface) Support"
depends on !IA64_HP_SIM
depends on IA64 || X86 || (ARM64 && EXPERT)
depends on IA64 || X86 || ARM64
depends on PCI
select PNP
default y
default y if (IA64 || X86)
help
Advanced Configuration and Power Interface (ACPI) support for
Linux requires an ACPI-compliant platform (hardware/firmware),
@ -311,12 +311,12 @@ config ACPI_CUSTOM_DSDT
bool
default ACPI_CUSTOM_DSDT_FILE != ""
config ACPI_INITRD_TABLE_OVERRIDE
bool "ACPI tables override via initrd"
config ACPI_TABLE_UPGRADE
bool "Allow upgrading ACPI tables via initrd"
depends on BLK_DEV_INITRD && X86
default n
default y
help
This option provides functionality to override arbitrary ACPI tables
This option provides functionality to upgrade arbitrary ACPI tables
via initrd. No functional change if no ACPI tables are passed via
initrd, therefore it's safe to say Y.
See Documentation/acpi/initrd_table_override.txt for details

View File

@ -18,7 +18,7 @@ obj-$(CONFIG_ACPI) += acpi.o \
acpica/
# All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o
acpi-y += osi.o osl.o utils.o reboot.o
acpi-y += nvs.o
# Power management related files
@ -47,6 +47,7 @@ acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o
acpi-y += int340x_thermal.o
acpi-y += power.o
acpi-y += event.o
acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o
acpi-y += sysfs.o
acpi-y += property.o
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o

View File

@ -35,8 +35,7 @@ static void amba_register_dummy_clk(void)
if (amba_dummy_clk)
return;
amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
CLK_IS_ROOT, 0);
amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0);
clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
}

View File

@ -62,8 +62,7 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
if (dev_desc->fixed_clk_rate) {
clk = clk_register_fixed_rate(&pdata->adev->dev,
dev_name(&pdata->adev->dev),
NULL, CLK_IS_ROOT,
dev_desc->fixed_clk_rate);
NULL, 0, dev_desc->fixed_clk_rate);
clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev));
pdata->clk = clk;
}

View File

@ -191,19 +191,6 @@ struct acpi_video_device_cap {
u8 _DDC:1; /* Return the EDID for this device */
};
struct acpi_video_brightness_flags {
u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
u8 _BCL_reversed:1; /* _BCL package is in a reversed order */
u8 _BQC_use_index:1; /* _BQC returns an index value */
};
struct acpi_video_device_brightness {
int curr;
int count;
int *levels;
struct acpi_video_brightness_flags flags;
};
struct acpi_video_device {
unsigned long device_id;
struct acpi_video_device_flags flags;
@ -325,7 +312,7 @@ static const struct thermal_cooling_device_ops video_cooling_ops = {
*/
static int
acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
acpi_video_device_lcd_query_levels(acpi_handle handle,
union acpi_object **levels)
{
int status;
@ -335,7 +322,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
*levels = NULL;
status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
status = acpi_evaluate_object(handle, "_BCL", NULL, &buffer);
if (!ACPI_SUCCESS(status))
return status;
obj = (union acpi_object *)buffer.pointer;
@ -766,36 +753,28 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
return 0;
}
/*
* Arg:
* device : video output device (LCD, CRT, ..)
*
* Return Value:
* Maximum brightness level
*
* Allocate and initialize device->brightness.
*/
static int
acpi_video_init_brightness(struct acpi_video_device *device)
int acpi_video_get_levels(struct acpi_device *device,
struct acpi_video_device_brightness **dev_br)
{
union acpi_object *obj = NULL;
int i, max_level = 0, count = 0, level_ac_battery = 0;
unsigned long long level, level_old;
union acpi_object *o;
struct acpi_video_device_brightness *br = NULL;
int result = -EINVAL;
int result = 0;
u32 value;
if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device->handle,
&obj))) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
"LCD brightness level\n"));
result = -ENODEV;
goto out;
}
if (obj->package.count < 2)
if (obj->package.count < 2) {
result = -EINVAL;
goto out;
}
br = kzalloc(sizeof(*br), GFP_KERNEL);
if (!br) {
@ -861,6 +840,38 @@ acpi_video_init_brightness(struct acpi_video_device *device)
"Found unordered _BCL package"));
br->count = count;
*dev_br = br;
out:
kfree(obj);
return result;
out_free:
kfree(br);
goto out;
}
EXPORT_SYMBOL(acpi_video_get_levels);
/*
* Arg:
* device : video output device (LCD, CRT, ..)
*
* Return Value:
* Maximum brightness level
*
* Allocate and initialize device->brightness.
*/
static int
acpi_video_init_brightness(struct acpi_video_device *device)
{
int i, max_level = 0;
unsigned long long level, level_old;
struct acpi_video_device_brightness *br = NULL;
int result = -EINVAL;
result = acpi_video_get_levels(device->dev, &br);
if (result)
return result;
device->brightness = br;
/* _BQC uses INDEX while _BCL uses VALUE in some laptops */
@ -903,17 +914,13 @@ set_level:
goto out_free_levels;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"found %d brightness levels\n", count - 2));
kfree(obj);
return result;
"found %d brightness levels\n", br->count - 2));
return 0;
out_free_levels:
kfree(br->levels);
out_free:
kfree(br);
out:
device->brightness = NULL;
kfree(obj);
return result;
}

View File

@ -43,6 +43,7 @@ acpi-y += \
evxfregn.o
acpi-y += \
exconcat.o \
exconfig.o \
exconvrt.o \
excreate.o \
@ -149,6 +150,7 @@ acpi-y += \
acpi-y += \
utaddress.o \
utalloc.o \
utascii.o \
utbuffer.o \
utcopy.o \
utexcep.o \

View File

@ -53,7 +53,7 @@
#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
struct acpi_db_command_info {
char *name; /* Command Name */
const char *name; /* Command Name */
u8 min_args; /* Minimum arguments required */
};
@ -64,7 +64,7 @@ struct acpi_db_command_help {
};
struct acpi_db_argument_info {
char *name; /* Argument Name */
const char *name; /* Argument Name */
};
struct acpi_db_execute_walk {

View File

@ -72,6 +72,7 @@ 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);
/*
@ -198,8 +199,6 @@ void
acpi_ev_detach_region(union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked);
void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj);
void
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
acpi_adr_space_type space_id, u32 function);

View File

@ -187,6 +187,8 @@ 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 char acpi_gbl_lower_hex_digits[];
extern const char acpi_gbl_upper_hex_digits[];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
@ -361,6 +363,15 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects);
#endif /* ACPI_DEBUGGER */
#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER)
ACPI_GLOBAL(const char, *acpi_gbl_pld_panel_list[]);
ACPI_GLOBAL(const char, *acpi_gbl_pld_vertical_position_list[]);
ACPI_GLOBAL(const char, *acpi_gbl_pld_horizontal_position_list[]);
ACPI_GLOBAL(const char, *acpi_gbl_pld_shape_list[]);
#endif
/*****************************************************************************
*
* Application globals

View File

@ -67,7 +67,7 @@
typedef const struct acpi_exdump_info {
u8 opcode;
u8 offset;
char *name;
const char *name;
} acpi_exdump_info;

View File

@ -395,11 +395,12 @@ union acpi_predefined_info {
/* Return object auto-repair info */
typedef acpi_status(*acpi_object_converter) (struct acpi_namespace_node * scope,
union acpi_operand_object
*original_object,
union acpi_operand_object
**converted_object);
typedef acpi_status (*acpi_object_converter) (struct acpi_namespace_node *
scope,
union acpi_operand_object *
original_object,
union acpi_operand_object **
converted_object);
struct acpi_simple_repair_info {
char name[ACPI_NAME_SIZE];
@ -541,8 +542,8 @@ struct acpi_gpe_device_info {
typedef acpi_status (*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
struct acpi_gpe_block_info *
gpe_block, void *context);
/* Information about each particular fixed event */
@ -660,7 +661,8 @@ typedef
acpi_status (*acpi_parse_downwards) (struct acpi_walk_state * walk_state,
union acpi_parse_object ** out_op);
typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state);
typedef
acpi_status (*acpi_parse_upwards) (struct acpi_walk_state * walk_state);
/* Global handlers for AML Notifies */
@ -700,7 +702,8 @@ union acpi_generic_state {
*
****************************************************************************/
typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state);
typedef
acpi_status (*acpi_execute_op) (struct acpi_walk_state * walk_state);
/* Address Range info block */
@ -854,7 +857,7 @@ struct acpi_parse_state {
/* Parse object flags */
#define ACPI_PARSEOP_GENERIC 0x01
#define ACPI_PARSEOP_NAMED 0x02
#define ACPI_PARSEOP_NAMED_OBJECT 0x02
#define ACPI_PARSEOP_DEFERRED 0x04
#define ACPI_PARSEOP_BYTELIST 0x08
#define ACPI_PARSEOP_IN_STACK 0x10
@ -864,11 +867,11 @@ struct acpi_parse_state {
/* Parse object disasm_flags */
#define ACPI_PARSEOP_IGNORE 0x01
#define ACPI_PARSEOP_PARAMLIST 0x02
#define ACPI_PARSEOP_PARAMETER_LIST 0x02
#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
#define ACPI_PARSEOP_PREDEF_CHECKED 0x08
#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x08
#define ACPI_PARSEOP_CLOSING_PAREN 0x10
#define ACPI_PARSEOP_COMPOUND 0x20
#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x20
#define ACPI_PARSEOP_ASSIGNMENT 0x40
#define ACPI_PARSEOP_ELSEIF 0x80
@ -1096,6 +1099,7 @@ struct acpi_external_list {
#define ACPI_EXT_ORIGIN_FROM_FILE 0x02 /* External came from a file */
#define ACPI_EXT_INTERNAL_PATH_ALLOCATED 0x04 /* Deallocate internal path on completion */
#define ACPI_EXT_EXTERNAL_EMITTED 0x08 /* External() statement has been emitted */
#define ACPI_EXT_ORIGIN_FROM_OPCODE 0x10 /* External came from a External() opcode */
struct acpi_external_file {
char *path;

View File

@ -260,14 +260,31 @@
#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1))
/* Generic (power-of-two) rounding */
#define ACPI_IS_ALIGNED(a, s) (((a) & ((s) - 1)) == 0)
#define ACPI_IS_POWER_OF_TWO(a) ACPI_IS_ALIGNED(a, a)
/*
* 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
* MASK_BITS_ABOVE/BELOW accpets a bit offset to create a mask
* MASK_BITS_ABOVE/BELOW_32/64 accpets a bit width to create a mask
* Note: The ACPI_INTEGER_BIT_SIZE check is used to bypass compiler
* differences with the shift operator
*/
#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_UINT64_MAX) << ((u32) (position))))
#define ACPI_MASK_BITS_BELOW(position) ((ACPI_UINT64_MAX) << ((u32) (position)))
#define ACPI_MASK_BITS_ABOVE_32(width) ((u32) ACPI_MASK_BITS_ABOVE(width))
#define ACPI_MASK_BITS_BELOW_32(width) ((u32) ACPI_MASK_BITS_BELOW(width))
#define ACPI_MASK_BITS_ABOVE_64(width) ((width) == ACPI_INTEGER_BIT_SIZE ? \
ACPI_UINT64_MAX : \
ACPI_MASK_BITS_ABOVE(width))
#define ACPI_MASK_BITS_BELOW_64(width) ((width) == ACPI_INTEGER_BIT_SIZE ? \
(u64) 0 : \
ACPI_MASK_BITS_BELOW(width))
/* Bitfields within ACPI registers */
@ -283,10 +300,10 @@
/* Generic bitfield macros and masks */
#define ACPI_GET_BITS(source_ptr, position, mask) \
((*source_ptr >> position) & mask)
((*(source_ptr) >> (position)) & (mask))
#define ACPI_SET_BITS(target_ptr, position, mask, value) \
(*target_ptr |= ((value & mask) << position))
(*(target_ptr) |= (((value) & (mask)) << (position)))
#define ACPI_1BIT_MASK 0x00000001
#define ACPI_2BIT_MASK 0x00000003

View File

@ -206,9 +206,10 @@ 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);
acpi_ns_dump_pathname(acpi_handle handle,
const char *msg, u32 level, u32 component);
void acpi_ns_print_pathname(u32 num_segments, char *pathname);
void acpi_ns_print_pathname(u32 num_segments, const char *pathname);
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,

View File

@ -139,7 +139,7 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
*/
const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
char *acpi_ps_get_opcode_name(u16 opcode);
const char *acpi_ps_get_opcode_name(u16 opcode);
u8 acpi_ps_get_argument_count(u32 op_type);

View File

@ -129,7 +129,8 @@ enum acpi_return_package_types {
ACPI_PTYPE2_REV_FIXED = 9,
ACPI_PTYPE2_FIX_VAR = 10,
ACPI_PTYPE2_VAR_VAR = 11,
ACPI_PTYPE2_UUID_PAIR = 12
ACPI_PTYPE2_UUID_PAIR = 12,
ACPI_PTYPE_CUSTOM = 13
};
/* Support macros for users of the predefined info table */
@ -340,7 +341,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_BIX", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (16 Int),(4 Str) */
PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,
PACKAGE_INFO(ACPI_PTYPE_CUSTOM, ACPI_RTYPE_INTEGER, 16,
ACPI_RTYPE_STRING, 4, 0),
{{"_BLT",
@ -523,6 +524,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */
PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0),
{{"_FIT", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, /* ACPI 6.0 */
{{"_FIX", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */
PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0),
@ -1053,6 +1057,12 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING |
ACPI_RTYPE_BUFFER)}},
{{"_WPC", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */
{{"_WPP", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */
PACKAGE_INFO(0, 0, 0, 0, 0, 0) /* Table terminator */
};
#else

View File

@ -124,7 +124,7 @@ typedef enum {
typedef const struct acpi_rsdump_info {
u8 opcode;
u8 offset;
char *name;
const char *name;
const char **pointer;
} acpi_rsdump_info;
@ -209,7 +209,7 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
acpi_status
acpi_rs_get_method_data(acpi_handle handle,
char *path, struct acpi_buffer *ret_buffer);
const char *path, struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,

View File

@ -184,7 +184,7 @@ 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 */
const 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) */

View File

@ -161,8 +161,6 @@ acpi_tb_install_fixed_table(acpi_physical_address address,
acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
u8 acpi_is_valid_signature(char *signature);
/*
* tbxfload
*/

View File

@ -166,6 +166,15 @@ struct acpi_pkg_info {
#define DB_DWORD_DISPLAY 4
#define DB_QWORD_DISPLAY 8
/*
* utascii - ASCII utilities
*/
u8 acpi_ut_valid_nameseg(char *signature);
u8 acpi_ut_valid_name_char(char character, u32 position);
void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count);
/*
* utnonansi - Non-ANSI C library functions
*/
@ -175,7 +184,14 @@ 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);
acpi_status
acpi_ut_strtoul64(char *string,
u32 base, u32 max_integer_byte_width, u64 *ret_integer);
/* Values for max_integer_byte_width above */
#define ACPI_MAX32_BYTE_WIDTH 4
#define ACPI_MAX64_BYTE_WIDTH 8
/*
* utglobal - Global data structures and procedures
@ -266,7 +282,8 @@ acpi_ut_trace(u32 line_number,
void
acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, void *pointer);
const char *module_name,
u32 component_id, const void *pointer);
void
acpi_ut_trace_u32(u32 line_number,
@ -276,7 +293,8 @@ acpi_ut_trace_u32(u32 line_number,
void
acpi_ut_trace_str(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, char *string);
const char *module_name,
u32 component_id, const char *string);
void
acpi_ut_exit(u32 line_number,
@ -335,12 +353,12 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
*/
acpi_status
acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
char *path,
const char *path,
u32 expected_return_btypes,
union acpi_operand_object **return_desc);
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
acpi_ut_evaluate_numeric_object(const char *object_name,
struct acpi_namespace_node *device_node,
u64 *value);
@ -526,7 +544,7 @@ void acpi_ut_set_integer_width(u8 revision);
void
acpi_ut_display_init_pathname(u8 type,
struct acpi_namespace_node *obj_handle,
char *path);
const char *path);
#endif
/*
@ -570,10 +588,6 @@ void acpi_ut_print_string(char *string, u16 max_length);
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)
@ -628,7 +642,7 @@ 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,
acpi_ut_create_list(const char *list_name,
u16 object_size, struct acpi_memory_list **return_cache);
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */

View File

@ -277,7 +277,9 @@ acpi_db_convert_to_object(acpi_object_type type,
default:
object->type = ACPI_TYPE_INTEGER;
status = acpi_ut_strtoul64(string, 16, &object->integer.value);
status =
acpi_ut_strtoul64(string, 16, acpi_gbl_integer_byte_width,
&object->integer.value);
break;
}

View File

@ -57,12 +57,12 @@ static u32 acpi_db_get_line(char *input_buffer);
static u32 acpi_db_match_command(char *user_command);
static void acpi_db_display_command_info(char *command, u8 display_all);
static void acpi_db_display_command_info(const char *command, u8 display_all);
static void acpi_db_display_help(char *command);
static u8
acpi_db_match_command_help(char *command,
acpi_db_match_command_help(const char *command,
const struct acpi_db_command_help *help);
/*
@ -348,7 +348,7 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = {
******************************************************************************/
static u8
acpi_db_match_command_help(char *command,
acpi_db_match_command_help(const char *command,
const struct acpi_db_command_help *help)
{
char *invocation = help->invocation;
@ -402,7 +402,7 @@ acpi_db_match_command_help(char *command,
*
******************************************************************************/
static void acpi_db_display_command_info(char *command, u8 display_all)
static void acpi_db_display_command_info(const char *command, u8 display_all)
{
const struct acpi_db_command_help *next;
u8 matched;
@ -656,8 +656,9 @@ static u32 acpi_db_match_command(char *user_command)
}
for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) {
if (strstr(acpi_gbl_db_commands[i].name, user_command) ==
acpi_gbl_db_commands[i].name) {
if (strstr
(ACPI_CAST_PTR(char, acpi_gbl_db_commands[i].name),
user_command) == acpi_gbl_db_commands[i].name) {
return (i);
}
}

View File

@ -709,7 +709,7 @@ acpi_db_integrity_walk(acpi_handle obj_handle,
return (AE_OK);
}
if (!acpi_ut_valid_acpi_name(node->name.ascii)) {
if (!acpi_ut_valid_nameseg(node->name.ascii)) {
acpi_os_printf("Invalid AcpiName for Node %p\n", node);
return (AE_OK);
}

View File

@ -56,8 +56,6 @@ 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
@ -82,8 +80,9 @@ acpi_db_match_argument(char *user_argument,
}
for (i = 0; arguments[i].name; i++) {
if (strstr(arguments[i].name, user_argument) ==
arguments[i].name) {
if (strstr(ACPI_CAST_PTR(char, arguments[i].name),
ACPI_CAST_PTR(char,
user_argument)) == arguments[i].name) {
return (i);
}
}
@ -339,7 +338,7 @@ void acpi_db_uint32_to_hex_string(u32 value, char *buffer)
buffer[8] = '\0';
for (i = 7; i >= 0; i--) {
buffer[i] = gbl_hex_to_ascii[value & 0x0F];
buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F];
value = value >> 4;
}
}

View File

@ -490,8 +490,8 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status =
acpi_ds_create_index_field(op,
(acpi_handle) arg->
common.node, walk_state);
(acpi_handle)arg->common.
node, walk_state);
break;
case AML_BANK_FIELD_OP:

View File

@ -99,8 +99,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
******************************************************************************/
acpi_status
acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
u32 notify_value)
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;

View File

@ -524,52 +524,6 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj,
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_associate_reg_method
*
* PARAMETERS: region_obj - Region object
*
* RETURN: Status
*
* DESCRIPTION: Find and associate _REG method to a region
*
******************************************************************************/
void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj)
{
acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
struct acpi_namespace_node *method_node;
struct acpi_namespace_node *node;
union acpi_operand_object *region_obj2;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_associate_reg_method);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_VOID;
}
node = region_obj->region.node->parent;
/* 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;
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_method
@ -589,18 +543,42 @@ 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;
const acpi_name *reg_name_ptr =
ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG);
struct acpi_namespace_node *method_node;
struct acpi_namespace_node *node;
acpi_status status;
ACPI_FUNCTION_TRACE(ev_execute_reg_method);
if (!acpi_gbl_namespace_initialized ||
region_obj->region.handler == NULL) {
return_ACPI_STATUS(AE_OK);
}
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 ||
region_obj->region.handler == NULL ||
!acpi_gbl_namespace_initialized) {
/*
* Find any "_REG" method associated with this region definition.
* The method should always be updated as this function may be
* invoked after a namespace change.
*/
node = region_obj->region.node->parent;
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;
}
if (region_obj2->extra.method_REG == NULL) {
return_ACPI_STATUS(AE_OK);
}

View File

@ -518,7 +518,6 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
return_ACPI_STATUS(AE_OK);
}
acpi_ev_associate_reg_method(region_obj);
region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
node = region_obj->region.node->parent;

View File

@ -0,0 +1,439 @@
/******************************************************************************
*
* Module Name: exconcat - Concatenate-type AML operators
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2016, 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 "amlresrc.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconcat")
/* Local Prototypes */
static acpi_status
acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc);
/*******************************************************************************
*
* 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 with the ACPI-defined conversion
* rules as necessary.
* NOTE:
* Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
* String, and Buffer objects. However, we support all objects here
* as an extension. This improves the usefulness of both Concatenate
* and the Printf/Fprintf macros. The extension returns a string
* describing the object type for the other objects.
* 02/2016.
*
******************************************************************************/
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_operand0 = operand0;
union acpi_operand_object *local_operand1 = operand1;
union acpi_operand_object *temp_operand1 = NULL;
union acpi_operand_object *return_desc;
char *buffer;
acpi_object_type operand0_type;
acpi_object_type operand1_type;
acpi_status status;
ACPI_FUNCTION_TRACE(ex_do_concatenate);
/* Operand 0 preprocessing */
switch (operand0->common.type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
operand0_type = operand0->common.type;
break;
default:
/* For all other types, get the "object type" string */
status =
acpi_ex_convert_to_object_type_string(operand0,
&local_operand0);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
operand0_type = ACPI_TYPE_STRING;
break;
}
/* Operand 1 preprocessing */
switch (operand1->common.type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
operand1_type = operand1->common.type;
break;
default:
/* For all other types, get the "object type" string */
status =
acpi_ex_convert_to_object_type_string(operand1,
&local_operand1);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
operand1_type = ACPI_TYPE_STRING;
break;
}
/*
* Convert the second operand if necessary. The first operand (0)
* determines the type of the second operand (1) (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_type) {
case ACPI_TYPE_INTEGER:
status =
acpi_ex_convert_to_integer(local_operand1, &temp_operand1,
16);
break;
case ACPI_TYPE_BUFFER:
status =
acpi_ex_convert_to_buffer(local_operand1, &temp_operand1);
break;
case ACPI_TYPE_STRING:
switch (operand1_type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Other types have already been converted to string */
status =
acpi_ex_convert_to_string(local_operand1,
&temp_operand1,
ACPI_IMPLICIT_CONVERT_HEX);
break;
default:
status = AE_OK;
break;
}
break;
default:
ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
operand0->common.type));
status = AE_AML_INTERNAL;
}
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Take care with any newly created operand objects */
if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) {
acpi_ut_remove_reference(local_operand1);
}
local_operand1 = temp_operand1;
/*
* 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, as per the ACPI spec:
*
* 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_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;
}
buffer = (char *)return_desc->buffer.pointer;
/* Copy the first integer, LSB first */
memcpy(buffer, &operand0->integer.value,
acpi_gbl_integer_byte_width);
/* Copy the second integer (LSB first) after the first */
memcpy(buffer + 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)
local_operand0->
string.length +
local_operand1->
string.length));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
buffer = return_desc->string.pointer;
/* Concatenate the strings */
strcpy(buffer, local_operand0->string.pointer);
strcat(buffer, 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;
}
buffer = (char *)return_desc->buffer.pointer;
/* Concatenate the buffers */
memcpy(buffer, operand0->buffer.pointer,
operand0->buffer.length);
memcpy(buffer + 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_operand0 != operand0) {
acpi_ut_remove_reference(local_operand0);
}
if (local_operand1 != operand1) {
acpi_ut_remove_reference(local_operand1);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_object_type_string
*
* PARAMETERS: obj_desc - Object to be converted
* return_desc - Where to place the return object
*
* RETURN: Status
*
* DESCRIPTION: Convert an object of arbitrary type to a string object that
* contains the namestring for the object. Used for the
* concatenate operator.
*
******************************************************************************/
static acpi_status
acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc)
{
union acpi_operand_object *return_desc;
const char *type_string;
type_string = acpi_ut_get_type_name(obj_desc->common.type);
return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9)); /* 9 For "[ Object]" */
if (!return_desc) {
return (AE_NO_MEMORY);
}
strcpy(return_desc->string.pointer, "[");
strcat(return_desc->string.pointer, type_string);
strcat(return_desc->string.pointer, " Object]");
*result_desc = return_desc;
return (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);
}

View File

@ -118,7 +118,9 @@ acpi_ex_add_table(u32 table_index,
/* Execute any module-level code that was found in the table */
acpi_ex_exit_interpreter();
if (acpi_gbl_group_module_level_code) {
acpi_ns_exec_module_code_list();
}
acpi_ex_enter_interpreter();
/*

View File

@ -124,7 +124,9 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
* 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);
status = acpi_ut_strtoul64((char *)pointer, flags,
acpi_gbl_integer_byte_width,
&result);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

View File

@ -55,9 +55,9 @@ ACPI_MODULE_NAME("exdump")
*/
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
static void acpi_ex_out_string(char *title, char *value);
static void acpi_ex_out_string(const char *title, const char *value);
static void acpi_ex_out_pointer(char *title, void *value);
static void acpi_ex_out_pointer(const char *title, const void *value);
static void
acpi_ex_dump_object(union acpi_operand_object *obj_desc,
@ -365,8 +365,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
struct acpi_exdump_info *info)
{
u8 *target;
char *name;
const char *reference_name;
const char *name;
u8 count;
union acpi_operand_object *start;
union acpi_operand_object *data = NULL;
@ -459,9 +458,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
case ACPI_EXD_REFERENCE:
reference_name = acpi_ut_get_reference_name(obj_desc);
acpi_ex_out_string("Class Name",
ACPI_CAST_PTR(char, reference_name));
acpi_ut_get_reference_name
(obj_desc));
acpi_ex_dump_reference_obj(obj_desc);
break;
@ -934,12 +933,12 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
*
******************************************************************************/
static void acpi_ex_out_string(char *title, char *value)
static void acpi_ex_out_string(const char *title, const char *value)
{
acpi_os_printf("%20s : %s\n", title, value);
}
static void acpi_ex_out_pointer(char *title, void *value)
static void acpi_ex_out_pointer(const char *title, const void *value)
{
acpi_os_printf("%20s : %p\n", title, value);
}

View File

@ -897,17 +897,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
/*
* Create the bitmasks used for bit insertion.
* Note: This if/else is used to bypass compiler differences with the
* shift operator
*/
if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
width_mask = ACPI_UINT64_MAX;
} else {
width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
}
/* Create the bitmasks used for bit insertion */
width_mask = ACPI_MASK_BITS_ABOVE_64(access_bit_width);
mask = width_mask &
ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);

View File

@ -45,7 +45,6 @@
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#include "amlresrc.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmisc")
@ -138,295 +137,6 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_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;
const char *type_string;
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:
/*
* Per the ACPI spec, Concatenate only supports int/str/buf.
* However, we support all objects here as an extension.
* This improves the usefulness of the Printf() macro.
* 12/2015.
*/
switch (operand1->common.type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
status =
acpi_ex_convert_to_string(operand1, &local_operand1,
ACPI_IMPLICIT_CONVERT_HEX);
break;
default:
/*
* Just emit a string containing the object type.
*/
type_string =
acpi_ut_get_type_name(operand1->common.type);
local_operand1 = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9)); /* 9 For "[Object]" */
if (!local_operand1) {
status = AE_NO_MEMORY;
goto cleanup;
}
strcpy(local_operand1->string.pointer, "[");
strcat(local_operand1->string.pointer, type_string);
strcat(local_operand1->string.pointer, " Object]");
status = AE_OK;
break;
}
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);
strcat(new_buf, 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

View File

@ -178,7 +178,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
for (index = 0;
(index < ACPI_NAME_SIZE)
&& (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
&& (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
char_buf[index] = *aml_address++;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
}

View File

@ -301,8 +301,8 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base)
*
* FUNCTION: acpi_ex_eisa_id_to_string
*
* PARAMETERS: compressed_id - EISAID to be converted
* out_string - Where to put the converted string (8 bytes)
* PARAMETERS: out_string - Where to put the converted string (8 bytes)
* compressed_id - EISAID to be converted
*
* RETURN: None
*
@ -354,7 +354,7 @@ void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id)
* possible 64-bit integer.
* value - Value to be converted
*
* RETURN: None, string
* RETURN: Converted string in out_string
*
* DESCRIPTION: Convert a 64-bit integer to decimal string representation.
* Assumes string buffer is large enough to hold the string. The
@ -384,9 +384,9 @@ void acpi_ex_integer_to_string(char *out_string, u64 value)
* 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)
* class_code - PCI class code to be converted (3 bytes)
*
* RETURN: None
* RETURN: Converted string in out_string
*
* DESCRIPTION: Convert 3-bytes PCI class code to string representation.
* Return buffer must be large enough to hold the string. The
@ -417,7 +417,7 @@ void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3])
*
* PARAMETERS: space_id - ID to be validated
*
* RETURN: TRUE if valid/supported ID.
* RETURN: TRUE if space_id is a valid/supported ID.
*
* DESCRIPTION: Validate an operation region space_ID.
*

View File

@ -51,6 +51,10 @@ ACPI_MODULE_NAME("hwregs")
#if (!ACPI_REDUCED_HARDWARE)
/* Local Prototypes */
static u8
acpi_hw_get_access_bit_width(struct acpi_generic_address *reg,
u8 max_bit_width);
static acpi_status
acpi_hw_read_multiple(u32 *value,
struct acpi_generic_address *register_a,
@ -63,6 +67,48 @@ acpi_hw_write_multiple(u32 value,
#endif /* !ACPI_REDUCED_HARDWARE */
/******************************************************************************
*
* FUNCTION: acpi_hw_get_access_bit_width
*
* PARAMETERS: reg - GAS register structure
* max_bit_width - Max bit_width supported (32 or 64)
*
* RETURN: Status
*
* DESCRIPTION: Obtain optimal access bit width
*
******************************************************************************/
static u8
acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
{
u64 address;
if (!reg->access_width) {
/*
* Detect old register descriptors where only the bit_width field
* makes senses. The target address is copied to handle possible
* alignment issues.
*/
ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!reg->bit_offset && reg->bit_width &&
ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
ACPI_IS_ALIGNED(reg->bit_width, 8) &&
ACPI_IS_ALIGNED(address, reg->bit_width)) {
return (reg->bit_width);
} else {
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
return (32);
} else {
return (max_bit_width);
}
}
} else {
return (1 << (reg->access_width + 2));
}
}
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_register
@ -83,6 +129,8 @@ acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address)
{
u8 bit_width;
u8 access_width;
/* Must have a valid pointer to a GAS structure */
@ -109,23 +157,25 @@ acpi_hw_validate_register(struct acpi_generic_address *reg,
return (AE_SUPPORT);
}
/* Validate the bit_width */
/* Validate the access_width */
if ((reg->bit_width != 8) &&
(reg->bit_width != 16) &&
(reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
if (reg->access_width > 4) {
ACPI_ERROR((AE_INFO,
"Unsupported register bit width: 0x%X",
reg->bit_width));
"Unsupported register access width: 0x%X",
reg->access_width));
return (AE_SUPPORT);
}
/* Validate the bit_offset. Just a warning for now. */
/* Validate the bit_width, convert access_width into number of bits */
if (reg->bit_offset != 0) {
access_width = acpi_hw_get_access_bit_width(reg, max_bit_width);
bit_width =
ACPI_ROUND_UP(reg->bit_offset + reg->bit_width, access_width);
if (max_bit_width < bit_width) {
ACPI_WARNING((AE_INFO,
"Unsupported register bit offset: 0x%X",
reg->bit_offset));
"Requested bit width 0x%X is smaller than register bit width 0x%X",
max_bit_width, bit_width));
return (AE_SUPPORT);
}
return (AE_OK);
@ -145,17 +195,19 @@ acpi_hw_validate_register(struct acpi_generic_address *reg,
* 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;
u8 access_width;
u32 bit_width;
u8 bit_offset;
u64 value64;
u32 value32;
u8 index;
acpi_status status;
ACPI_FUNCTION_NAME(hw_read);
@ -167,28 +219,75 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
return (status);
}
/* Initialize entire 32-bit return value to zero */
/*
* Initialize entire 32-bit return value to zero, convert access_width
* into number of bits based
*/
*value = 0;
access_width = acpi_hw_get_access_bit_width(reg, 32);
bit_width = reg->bit_offset + reg->bit_width;
bit_offset = reg->bit_offset;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
index = 0;
while (bit_width) {
if (bit_offset >= access_width) {
value32 = 0;
bit_offset -= access_width;
} else {
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;
status =
acpi_os_read_memory((acpi_physical_address)
address +
index *
ACPI_DIV_8
(access_width),
&value64, access_width);
value32 = (u32)value64;
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_read_port((acpi_io_address)
address, value, reg->bit_width);
address +
index *
ACPI_DIV_8
(access_width),
&value32,
access_width);
}
/*
* Use offset style bit masks because:
* bit_offset < access_width/bit_width < access_width, and
* access_width is ensured to be less than 32-bits by
* acpi_hw_validate_register().
*/
if (bit_offset) {
value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
bit_offset = 0;
}
if (bit_width < access_width) {
value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
}
}
/*
* Use offset style bit writes because "Index * AccessWidth" is
* ensured to be less than 32-bits by acpi_hw_validate_register().
*/
ACPI_SET_BITS(value, index * access_width,
ACPI_MASK_BITS_ABOVE_32(access_width), value32);
bit_width -=
bit_width > access_width ? access_width : bit_width;
index++;
}
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),
*value, access_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
@ -212,6 +311,12 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
u64 address;
u8 access_width;
u32 bit_width;
u8 bit_offset;
u64 value64;
u32 new_value32, old_value32;
u8 index;
acpi_status status;
ACPI_FUNCTION_NAME(hw_write);
@ -223,23 +328,145 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
return (status);
}
/* Convert access_width into number of bits based */
access_width = acpi_hw_get_access_bit_width(reg, 32);
bit_width = reg->bit_offset + reg->bit_width;
bit_offset = reg->bit_offset;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
index = 0;
while (bit_width) {
/*
* Use offset style bit reads because "Index * AccessWidth" is
* ensured to be less than 32-bits by acpi_hw_validate_register().
*/
new_value32 = ACPI_GET_BITS(&value, index * access_width,
ACPI_MASK_BITS_ABOVE_32
(access_width));
if (bit_offset >= access_width) {
bit_offset -= access_width;
} else {
/*
* Use offset style bit masks because access_width is ensured
* to be less than 32-bits by acpi_hw_validate_register() and
* bit_offset/bit_width is less than access_width here.
*/
if (bit_offset) {
new_value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
}
if (bit_width < access_width) {
new_value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
}
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, (u64)value,
reg->bit_width);
if (bit_offset || bit_width < access_width) {
/*
* Read old values in order not to modify the bits that
* are beyond the register bit_width/bit_offset setting.
*/
status =
acpi_os_read_memory((acpi_physical_address)
address +
index *
ACPI_DIV_8
(access_width),
&value64,
access_width);
old_value32 = (u32)value64;
/*
* Use offset style bit masks because access_width is
* ensured to be less than 32-bits by
* acpi_hw_validate_register() and bit_offset/bit_width is
* less than access_width here.
*/
if (bit_offset) {
old_value32 &=
ACPI_MASK_BITS_ABOVE
(bit_offset);
bit_offset = 0;
}
if (bit_width < access_width) {
old_value32 &=
ACPI_MASK_BITS_BELOW
(bit_width);
}
new_value32 |= old_value32;
}
value64 = (u64)new_value32;
status =
acpi_os_write_memory((acpi_physical_address)
address +
index *
ACPI_DIV_8
(access_width),
value64, access_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
if (bit_offset || bit_width < access_width) {
/*
* Read old values in order not to modify the bits that
* are beyond the register bit_width/bit_offset setting.
*/
status =
acpi_hw_read_port((acpi_io_address)
address +
index *
ACPI_DIV_8
(access_width),
&old_value32,
access_width);
/*
* Use offset style bit masks because access_width is
* ensured to be less than 32-bits by
* acpi_hw_validate_register() and bit_offset/bit_width is
* less than access_width here.
*/
if (bit_offset) {
old_value32 &=
ACPI_MASK_BITS_ABOVE
(bit_offset);
bit_offset = 0;
}
if (bit_width < access_width) {
old_value32 &=
ACPI_MASK_BITS_BELOW
(bit_width);
}
new_value32 |= old_value32;
}
status = acpi_hw_write_port((acpi_io_address)
address, value, reg->bit_width);
address +
index *
ACPI_DIV_8
(access_width),
new_value32,
access_width);
}
}
/*
* Index * access_width is ensured to be less than 32-bits by
* acpi_hw_validate_register().
*/
bit_width -=
bit_width > access_width ? access_width : bit_width;
index++;
}
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),
value, access_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);

View File

@ -91,8 +91,7 @@ acpi_status acpi_reset(void)
* compatibility with other ACPI implementations that have allowed
* BIOS code with bad register width values to go unnoticed.
*/
status =
acpi_os_write_port((acpi_io_address) reset_reg->address,
status = acpi_os_write_port((acpi_io_address)reset_reg->address,
acpi_gbl_FADT.reset_value,
ACPI_RESET_REGISTER_WIDTH);
} else {
@ -504,9 +503,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
* Evaluate the \_Sx namespace object containing the register values
* for this state
*/
info->relative_pathname = ACPI_CAST_PTR(char,
acpi_gbl_sleep_state_names
[sleep_state]);
info->relative_pathname = acpi_gbl_sleep_state_names[sleep_state];
status = acpi_ns_evaluate(info);
if (ACPI_FAILURE(status)) {

View File

@ -107,9 +107,10 @@ acpi_status acpi_ns_root_initialize(void)
continue;
}
status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
ACPI_IMODE_LOAD_PASS2,
ACPI_NS_NO_UPSEARCH, NULL, &new_node);
status =
acpi_ns_lookup(NULL, (char *)init_val->name, init_val->type,
ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
NULL, &new_node);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not create predefined name %s",

View File

@ -79,7 +79,8 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
/* String-to-Integer conversion */
status = acpi_ut_strtoul64(original_object->string.pointer,
ACPI_ANY_BASE, &value);
ACPI_ANY_BASE,
acpi_gbl_integer_byte_width, &value);
if (ACPI_FAILURE(status)) {
return (status);
}

View File

@ -81,7 +81,7 @@ acpi_ns_get_max_depth(acpi_handle obj_handle,
*
******************************************************************************/
void acpi_ns_print_pathname(u32 num_segments, char *pathname)
void acpi_ns_print_pathname(u32 num_segments, const char *pathname)
{
u32 i;
@ -114,6 +114,9 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname)
acpi_os_printf("]\n");
}
#ifdef ACPI_OBSOLETE_FUNCTIONS
/* Not used at this time, perhaps later */
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_pathname
@ -131,7 +134,8 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname)
******************************************************************************/
void
acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
acpi_ns_dump_pathname(acpi_handle handle,
const char *msg, u32 level, u32 component)
{
ACPI_FUNCTION_TRACE(ns_dump_pathname);
@ -148,6 +152,7 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
acpi_os_printf("\n");
return_VOID;
}
#endif
/*******************************************************************************
*

View File

@ -140,6 +140,7 @@ acpi_status acpi_ns_initialize_devices(u32 flags)
{
acpi_status status = AE_OK;
struct acpi_device_walk_info info;
acpi_handle handle;
ACPI_FUNCTION_TRACE(ns_initialize_devices);
@ -190,6 +191,27 @@ acpi_status acpi_ns_initialize_devices(u32 flags)
if (ACPI_SUCCESS(status)) {
info.num_INI++;
}
/*
* Execute \_SB._INI.
* There appears to be a strict order requirement for \_SB._INI,
* which should be evaluated before any _REG evaluations.
*/
status = acpi_get_handle(NULL, "\\_SB", &handle);
if (ACPI_SUCCESS(status)) {
memset(info.evaluate_info, 0,
sizeof(struct acpi_evaluate_info));
info.evaluate_info->prefix_node = handle;
info.evaluate_info->relative_pathname =
METHOD_NAME__INI;
info.evaluate_info->parameters = NULL;
info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info.evaluate_info);
if (ACPI_SUCCESS(status)) {
info.num_INI++;
}
}
}
/*
@ -198,6 +220,12 @@ acpi_status acpi_ns_initialize_devices(u32 flags)
* Note: Any objects accessed by the _REG methods will be automatically
* initialized, even if they contain executable AML (see the call to
* acpi_ns_initialize_objects below).
*
* Note: According to the ACPI specification, we actually needn't execute
* _REG for system_memory/system_io operation regions, but for PCI_Config
* operation regions, it is required to evaluate _REG for those on a PCI
* root bus that doesn't contain _BBN object. So this code is kept here
* in order not to break things.
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@ -592,8 +620,11 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
* Note: We know there is an _INI within this subtree, but it may not be
* under this particular device, it may be lower in the branch.
*/
if (!ACPI_COMPARE_NAME(device_node->name.ascii, "_SB_") ||
device_node->parent != acpi_gbl_root_node) {
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));
(ACPI_TYPE_METHOD, device_node,
METHOD_NAME__INI));
memset(info, 0, sizeof(struct acpi_evaluate_info));
info->prefix_node = device_node;
@ -602,7 +633,6 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info);
if (ACPI_SUCCESS(status)) {
walk_info->num_INI++;
}
@ -614,11 +644,13 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
char *scope_name =
acpi_ns_get_normalized_pathname(device_node, TRUE);
ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
ACPI_EXCEPTION((AE_INFO, status,
"during %s._INI execution",
scope_name));
ACPI_FREE(scope_name);
}
#endif
}
/* Ignore errors from above */

View File

@ -123,8 +123,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
tables[table_index].owner_id);
acpi_tb_release_owner_id(table_index);
acpi_tb_release_owner_id(table_index);
return_ACPI_STATUS(status);
}

View File

@ -62,6 +62,10 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
u32 count1,
u8 type2, u32 count2, u32 start_index);
static acpi_status
acpi_ns_custom_package(struct acpi_evaluate_info *info,
union acpi_operand_object **elements, u32 count);
/*******************************************************************************
*
* FUNCTION: acpi_ns_check_package
@ -135,6 +139,11 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
* PTYPE2 packages contain subpackages
*/
switch (package->ret_info.type) {
case ACPI_PTYPE_CUSTOM:
status = acpi_ns_custom_package(info, elements, count);
break;
case ACPI_PTYPE1_FIXED:
/*
* The package count is fixed and there are no subpackages
@ -179,6 +188,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
if (ACPI_FAILURE(status)) {
return (status);
}
elements++;
}
break;
@ -225,6 +235,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
return (status);
}
}
elements++;
}
break;
@ -569,11 +580,13 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info,
if (sub_package->package.count < expected_count) {
goto package_too_small;
}
if (sub_package->package.count <
package->ret_info.count1) {
expected_count = package->ret_info.count1;
goto package_too_small;
}
if (expected_count == 0) {
/*
* Either the num_entries element was originally zero or it was
@ -620,6 +633,83 @@ package_too_small:
return (AE_AML_OPERAND_VALUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_custom_package
*
* PARAMETERS: info - Method execution information block
* elements - Pointer to the package elements array
* count - Element count for the package
*
* RETURN: Status
*
* DESCRIPTION: Check a returned package object for the correct count and
* correct type of all sub-objects.
*
* NOTE: Currently used for the _BIX method only. When needed for two or more
* methods, probably a detect/dispatch mechanism will be required.
*
******************************************************************************/
static acpi_status
acpi_ns_custom_package(struct acpi_evaluate_info *info,
union acpi_operand_object **elements, u32 count)
{
u32 expected_count;
u32 version;
acpi_status status = AE_OK;
ACPI_FUNCTION_NAME(ns_custom_package);
/* Get version number, must be Integer */
if ((*elements)->common.type != ACPI_TYPE_INTEGER) {
ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
info->node_flags,
"Return Package has invalid object type for version number"));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
version = (u32)(*elements)->integer.value;
expected_count = 21; /* Version 1 */
if (version == 0) {
expected_count = 20; /* Version 0 */
}
if (count < expected_count) {
ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
info->node_flags,
"Return Package is too small - found %u elements, expected %u",
count, expected_count));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
} else if (count > expected_count) {
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Return Package is larger than needed - "
"found %u, expected %u\n",
info->full_pathname, count, expected_count));
}
/* Validate all elements of the returned package */
status = acpi_ns_check_package_elements(info, elements,
ACPI_RTYPE_INTEGER, 16,
ACPI_RTYPE_STRING, 4, 0);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Version 1 has a single trailing integer */
if (version > 0) {
status = acpi_ns_check_package_elements(info, elements + 20,
ACPI_RTYPE_INTEGER, 1,
0, 0, 20);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_check_package_elements
@ -661,6 +751,7 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
if (ACPI_FAILURE(status)) {
return (status);
}
this_element++;
}
@ -671,6 +762,7 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
if (ACPI_FAILURE(status)) {
return (status);
}
this_element++;
}

View File

@ -55,8 +55,8 @@ ACPI_MODULE_NAME("nsrepair2")
*/
typedef
acpi_status (*acpi_repair_function) (struct acpi_evaluate_info * info,
union acpi_operand_object
**return_object_ptr);
union acpi_operand_object **
return_object_ptr);
typedef struct acpi_repair_info {
char name[ACPI_NAME_SIZE];

View File

@ -280,13 +280,12 @@ acpi_evaluate_object(acpi_handle handle,
info->parameters[info->param_count] = NULL;
}
#if 0
#ifdef _FUTURE_FEATURE
/*
* Begin incoming argument count analysis. Check for too few args
* and too many args.
*/
switch (acpi_ns_get_type(info->node)) {
case ACPI_TYPE_METHOD:
@ -370,10 +369,15 @@ acpi_evaluate_object(acpi_handle handle,
* If we are expecting a return value, and all went well above,
* copy the return value to an external object.
*/
if (return_buffer) {
if (!return_buffer) {
goto cleanup_return_object;
}
if (!info->return_object) {
return_buffer->length = 0;
} else {
goto cleanup;
}
if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
ACPI_DESC_TYPE_NAMED) {
/*
@ -389,7 +393,9 @@ acpi_evaluate_object(acpi_handle handle,
return_buffer->length = 0;
}
if (ACPI_SUCCESS(status)) {
if (ACPI_FAILURE(status)) {
goto cleanup_return_object;
}
/* Dereference Index and ref_of references */
@ -397,16 +403,13 @@ acpi_evaluate_object(acpi_handle handle,
/* Get the size of the returned object */
status =
acpi_ut_get_object_size(info->return_object,
status = acpi_ut_get_object_size(info->return_object,
&buffer_space_needed);
if (ACPI_SUCCESS(status)) {
/* Validate/Allocate/Clear caller buffer */
status =
acpi_ut_initialize_buffer
(return_buffer,
status = acpi_ut_initialize_buffer(return_buffer,
buffer_space_needed);
if (ACPI_FAILURE(status)) {
/*
@ -415,22 +418,18 @@ acpi_evaluate_object(acpi_handle handle,
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Needed buffer size %X, %s\n",
(u32)
buffer_space_needed,
acpi_format_exception
(status)));
(u32)buffer_space_needed,
acpi_format_exception(status)));
} else {
/* We have enough space for the object, build it */
status =
acpi_ut_copy_iobject_to_eobject
(info->return_object,
acpi_ut_copy_iobject_to_eobject(info->return_object,
return_buffer);
}
}
}
}
}
cleanup_return_object:
if (info->return_object) {
/*

View File

@ -158,7 +158,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
*
******************************************************************************/
char *acpi_ps_get_opcode_name(u16 opcode)
const char *acpi_ps_get_opcode_name(u16 opcode)
{
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)

View File

@ -128,7 +128,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml)
if (op_info->flags & AML_DEFER) {
flags = ACPI_PARSEOP_DEFERRED;
} else if (op_info->flags & AML_NAMED) {
flags = ACPI_PARSEOP_NAMED;
flags = ACPI_PARSEOP_NAMED_OBJECT;
} else if (opcode == AML_INT_BYTELIST_OP) {
flags = ACPI_PARSEOP_BYTELIST;
}

View File

@ -52,17 +52,17 @@ ACPI_MODULE_NAME("rsdump")
* All functions in this module are used by the AML Debugger only
*/
/* Local prototypes */
static void acpi_rs_out_string(char *title, char *value);
static void acpi_rs_out_string(const char *title, const char *value);
static void acpi_rs_out_integer8(char *title, u8 value);
static void acpi_rs_out_integer8(const char *title, u8 value);
static void acpi_rs_out_integer16(char *title, u16 value);
static void acpi_rs_out_integer16(const char *title, u16 value);
static void acpi_rs_out_integer32(char *title, u32 value);
static void acpi_rs_out_integer32(const char *title, u32 value);
static void acpi_rs_out_integer64(char *title, u64 value);
static void acpi_rs_out_integer64(const char *title, u64 value);
static void acpi_rs_out_title(char *title);
static void acpi_rs_out_title(const char *title);
static void acpi_rs_dump_byte_list(u16 length, u8 *data);
@ -208,7 +208,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
{
u8 *target = NULL;
u8 *previous_target;
char *name;
const char *name;
u8 count;
/* First table entry must contain the table length (# of table entries) */
@ -248,10 +248,8 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
case ACPI_RSD_UINT8:
if (table->pointer) {
acpi_rs_out_string(name, ACPI_CAST_PTR(char,
table->
pointer
[*target]));
acpi_rs_out_string(name,
table->pointer[*target]);
} else {
acpi_rs_out_integer8(name, ACPI_GET8(target));
}
@ -276,26 +274,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
case ACPI_RSD_1BITFLAG:
acpi_rs_out_string(name, ACPI_CAST_PTR(char,
table->
pointer[*target &
0x01]));
acpi_rs_out_string(name,
table->pointer[*target & 0x01]);
break;
case ACPI_RSD_2BITFLAG:
acpi_rs_out_string(name, ACPI_CAST_PTR(char,
table->
pointer[*target &
0x03]));
acpi_rs_out_string(name,
table->pointer[*target & 0x03]);
break;
case ACPI_RSD_3BITFLAG:
acpi_rs_out_string(name, ACPI_CAST_PTR(char,
table->
pointer[*target &
0x07]));
acpi_rs_out_string(name,
table->pointer[*target & 0x07]);
break;
case ACPI_RSD_SHORTLIST:
@ -481,7 +473,7 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource)
*
******************************************************************************/
static void acpi_rs_out_string(char *title, char *value)
static void acpi_rs_out_string(const char *title, const char *value)
{
acpi_os_printf("%27s : %s", title, value);
@ -491,30 +483,30 @@ static void acpi_rs_out_string(char *title, char *value)
acpi_os_printf("\n");
}
static void acpi_rs_out_integer8(char *title, u8 value)
static void acpi_rs_out_integer8(const char *title, u8 value)
{
acpi_os_printf("%27s : %2.2X\n", title, value);
}
static void acpi_rs_out_integer16(char *title, u16 value)
static void acpi_rs_out_integer16(const char *title, u16 value)
{
acpi_os_printf("%27s : %4.4X\n", title, value);
}
static void acpi_rs_out_integer32(char *title, u32 value)
static void acpi_rs_out_integer32(const char *title, u32 value)
{
acpi_os_printf("%27s : %8.8X\n", title, value);
}
static void acpi_rs_out_integer64(char *title, u64 value)
static void acpi_rs_out_integer64(const char *title, u64 value)
{
acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
}
static void acpi_rs_out_title(char *title)
static void acpi_rs_out_title(const char *title)
{
acpi_os_printf("%27s : ", title);

View File

@ -330,19 +330,20 @@ struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = {
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.connection_sharing),"ConnectionSharing", acpi_gbl_shr_decode}, \
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \
{ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL},
struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = {
struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[11] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus),
"Common Serial Bus", NULL},
ACPI_RS_DUMP_COMMON_SERIAL_BUS
};
struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = {
struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[14] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus),
"I2C Serial Bus", NULL},
ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
@ -355,7 +356,7 @@ struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = {
"SlaveAddress", NULL},
};
struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = {
struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[18] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus),
"Spi Serial Bus", NULL},
ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
@ -376,7 +377,7 @@ struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = {
"ConnectionSpeed", NULL},
};
struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = {
struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[20] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus),
"Uart Serial Bus", NULL},
ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG,

View File

@ -151,7 +151,7 @@ struct acpi_rsconvert_info acpi_rs_convert_gpio[18] = {
*
******************************************************************************/
struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[17] = {
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
ACPI_RSC_TABLE_SIZE(acpi_rs_convert_i2c_serial_bus)},
@ -177,6 +177,11 @@ struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
AML_OFFSET(common_serial_bus.flags),
1},
{ACPI_RSC_1BITFLAG,
ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
AML_OFFSET(common_serial_bus.flags),
2},
{ACPI_RSC_MOVE8,
ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
AML_OFFSET(common_serial_bus.type_revision_id),
@ -237,7 +242,7 @@ struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
*
******************************************************************************/
struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[21] = {
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
ACPI_RSC_TABLE_SIZE(acpi_rs_convert_spi_serial_bus)},
@ -263,6 +268,11 @@ struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
AML_OFFSET(common_serial_bus.flags),
1},
{ACPI_RSC_1BITFLAG,
ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
AML_OFFSET(common_serial_bus.flags),
2},
{ACPI_RSC_MOVE8,
ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
AML_OFFSET(common_serial_bus.type_revision_id),
@ -339,7 +349,7 @@ struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
*
******************************************************************************/
struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = {
struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[23] = {
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
ACPI_RSC_TABLE_SIZE(acpi_rs_convert_uart_serial_bus)},
@ -365,6 +375,11 @@ struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = {
AML_OFFSET(common_serial_bus.flags),
1},
{ACPI_RSC_1BITFLAG,
ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
AML_OFFSET(common_serial_bus.flags),
2},
{ACPI_RSC_MOVE8,
ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
AML_OFFSET(common_serial_bus.type_revision_id),

View File

@ -671,7 +671,7 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
acpi_status
acpi_rs_get_method_data(acpi_handle handle,
char *path, struct acpi_buffer *ret_buffer)
const char *path, struct acpi_buffer *ret_buffer)
{
union acpi_operand_object *obj_desc;
acpi_status status;

View File

@ -401,7 +401,7 @@ acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc, char *signature)
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
"%4.4s 0x%8.8X%8.8X"
" Attempted table install failed",
acpi_ut_valid_acpi_name(table_desc->
acpi_ut_valid_nameseg(table_desc->
signature.
ascii) ?
table_desc->signature.ascii : "????",
@ -467,8 +467,7 @@ acpi_status acpi_tb_resize_root_table_list(void)
if (acpi_gbl_root_table_list.tables) {
memcpy(tables, acpi_gbl_root_table_list.tables,
(acpi_size) table_count *
sizeof(struct acpi_table_desc));
(acpi_size)table_count * sizeof(struct acpi_table_desc));
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);

View File

@ -53,7 +53,7 @@ static void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id,
u8 byte_width,
u64 address, char *register_name, u8 flags);
u64 address, const char *register_name, u8 flags);
static void acpi_tb_convert_fadt(void);
@ -65,7 +65,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64);
/* Table for conversion of FADT to common internal format and FADT validation */
typedef struct acpi_fadt_info {
char *name;
const char *name;
u16 address64;
u16 address32;
u16 length;
@ -192,7 +192,7 @@ static void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id,
u8 byte_width,
u64 address, char *register_name, u8 flags)
u64 address, const char *register_name, u8 flags)
{
u8 bit_width;
@ -385,14 +385,15 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
/*
* Check if the FADT is larger than the largest table that we expect
* (the ACPI 5.0 version). If so, truncate the table, and issue
* a warning.
* (typically the current ACPI specification version). If so, truncate
* the table, and issue a warning.
*/
if (length > sizeof(struct acpi_table_fadt)) {
ACPI_BIOS_WARNING((AE_INFO,
"FADT (revision %u) is longer than ACPI 5.0 version, "
"FADT (revision %u) is longer than %s length, "
"truncating length %u to %u",
table->revision, length,
table->revision, ACPI_FADT_CONFORMANCE,
length,
(u32)sizeof(struct acpi_table_fadt)));
}
@ -467,7 +468,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
static void acpi_tb_convert_fadt(void)
{
char *name;
const char *name;
struct acpi_generic_address *address64;
u32 address32;
u8 length;
@ -646,9 +647,12 @@ static void acpi_tb_convert_fadt(void)
if ((address64->address && !length) ||
(!address64->address && length)) {
ACPI_BIOS_WARNING((AE_INFO,
"Optional FADT field %s has zero address or length: "
"0x%8.8X%8.8X/0x%X",
name,
"Optional FADT field %s has valid %s but zero %s: "
"0x%8.8X%8.8X/0x%X", name,
(length ? "Length" :
"Address"),
(length ? "Address" :
"Length"),
ACPI_FORMAT_UINT64
(address64->address),
length));

View File

@ -76,7 +76,7 @@ acpi_tb_find_table(char *signature,
/* Validate the input table signature */
if (!acpi_is_valid_signature(signature)) {
if (!acpi_ut_valid_nameseg(signature)) {
return_ACPI_STATUS(AE_BAD_SIGNATURE);
}

View File

@ -299,7 +299,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
ACPI_BIOS_ERROR((AE_INFO,
"Table has invalid signature [%4.4s] (0x%8.8X), "
"must be SSDT or OEMx",
acpi_ut_valid_acpi_name(new_table_desc.
acpi_ut_valid_nameseg(new_table_desc.
signature.
ascii) ?
new_table_desc.signature.

View File

@ -380,30 +380,3 @@ next_table:
acpi_os_unmap_memory(table, length);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_is_valid_signature
*
* PARAMETERS: signature - Sig string to be validated
*
* RETURN: TRUE if signature is has 4 valid ACPI characters
*
* DESCRIPTION: Validate an ACPI table signature.
*
******************************************************************************/
u8 acpi_is_valid_signature(char *signature)
{
u32 i;
/* Validate each character in the signature */
for (i = 0; i < ACPI_NAME_SIZE; i++) {
if (!acpi_ut_valid_acpi_char(signature[i], i)) {
return (FALSE);
}
}
return (TRUE);
}

View File

@ -82,7 +82,7 @@ acpi_status __init acpi_load_tables(void)
* their customized default region handlers.
*/
status = acpi_ev_install_region_handlers();
if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"During Region initialization"));
return_ACPI_STATUS(status);

View File

@ -272,8 +272,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
******************************************************************************/
acpi_status
acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
acpi_size required_length)
acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length)
{
acpi_size input_buffer_length;

View File

@ -0,0 +1,140 @@
/******************************************************************************
*
* Module Name: utascii - Utility ascii functions
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2016, 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"
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_nameseg
*
* PARAMETERS: name - The name or table signature to be examined.
* Four characters, does not have to be a
* NULL terminated string.
*
* RETURN: TRUE if signature is has 4 valid ACPI characters
*
* DESCRIPTION: Validate an ACPI table signature.
*
******************************************************************************/
u8 acpi_ut_valid_nameseg(char *name)
{
u32 i;
/* Validate each character in the signature */
for (i = 0; i < ACPI_NAME_SIZE; i++) {
if (!acpi_ut_valid_name_char(name[i], i)) {
return (FALSE);
}
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_name_char
*
* PARAMETERS: char - The character to be examined
* position - Byte position (0-3)
*
* RETURN: TRUE if the character is valid, FALSE otherwise
*
* DESCRIPTION: Check for a valid ACPI character. Must be one of:
* 1) Upper case alpha
* 2) numeric
* 3) underscore
*
* We allow a '!' as the last character because of the ASF! table
*
******************************************************************************/
u8 acpi_ut_valid_name_char(char character, u32 position)
{
if (!((character >= 'A' && character <= 'Z') ||
(character >= '0' && character <= '9') || (character == '_'))) {
/* Allow a '!' in the last position */
if (character == '!' && position == 3) {
return (TRUE);
}
return (FALSE);
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_check_and_repair_ascii
*
* PARAMETERS: name - Ascii string
* count - Number of characters to check
*
* RETURN: None
*
* DESCRIPTION: Ensure that the requested number of characters are printable
* Ascii characters. Sets non-printable and null chars to <space>.
*
******************************************************************************/
void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count)
{
u32 i;
for (i = 0; i < count; i++) {
repaired_name[i] = (char)name[i];
if (!name[i]) {
return;
}
if (!isprint(name[i])) {
repaired_name[i] = ' ';
}
}
}

View File

@ -184,8 +184,7 @@ acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
*
******************************************************************************/
acpi_status
acpi_os_release_object(struct acpi_memory_list * cache, void *object)
acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)
{
acpi_status status;

View File

@ -51,13 +51,9 @@
ACPI_MODULE_NAME("utdebug")
#ifdef ACPI_DEBUG_OUTPUT
static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF;
static char *acpi_gbl_fn_entry_str = "----Entry";
static char *acpi_gbl_fn_exit_str = "----Exit-";
/* Local prototypes */
static const char *acpi_ut_trim_function_name(const char *function_name);
static acpi_thread_id acpi_gbl_previous_thread_id = (acpi_thread_id) 0xFFFFFFFF;
static const char *acpi_gbl_function_entry_prefix = "----Entry";
static const char *acpi_gbl_function_exit_prefix = "----Exit-";
/*******************************************************************************
*
@ -178,14 +174,14 @@ acpi_debug_print(u32 requested_debug_level,
* Thread tracking and context switch notification
*/
thread_id = acpi_os_get_thread_id();
if (thread_id != acpi_gbl_prev_thread_id) {
if (thread_id != acpi_gbl_previous_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
("\n**** Context Switch from TID %u to TID %u ****\n\n",
(u32)acpi_gbl_prev_thread_id, (u32)thread_id);
(u32)acpi_gbl_previous_thread_id, (u32)thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
acpi_gbl_previous_thread_id = thread_id;
acpi_gbl_nesting_level = 0;
}
@ -287,7 +283,8 @@ acpi_ut_trace(u32 line_number,
if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s\n", acpi_gbl_fn_entry_str);
component_id, "%s\n",
acpi_gbl_function_entry_prefix);
}
}
@ -312,7 +309,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
void
acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, void *pointer)
const char *module_name,
u32 component_id, const void *pointer)
{
acpi_gbl_nesting_level++;
@ -323,8 +321,8 @@ acpi_ut_trace_ptr(u32 line_number,
if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s %p\n", acpi_gbl_fn_entry_str,
pointer);
component_id, "%s %p\n",
acpi_gbl_function_entry_prefix, pointer);
}
}
@ -348,7 +346,7 @@ acpi_ut_trace_ptr(u32 line_number,
void
acpi_ut_trace_str(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, char *string)
const char *module_name, u32 component_id, const char *string)
{
acpi_gbl_nesting_level++;
@ -359,8 +357,8 @@ acpi_ut_trace_str(u32 line_number,
if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s %s\n", acpi_gbl_fn_entry_str,
string);
component_id, "%s %s\n",
acpi_gbl_function_entry_prefix, string);
}
}
@ -396,7 +394,7 @@ acpi_ut_trace_u32(u32 line_number,
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s %08X\n",
acpi_gbl_fn_entry_str, integer);
acpi_gbl_function_entry_prefix, integer);
}
}
@ -427,7 +425,8 @@ acpi_ut_exit(u32 line_number,
if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s\n", acpi_gbl_fn_exit_str);
component_id, "%s\n",
acpi_gbl_function_exit_prefix);
}
if (acpi_gbl_nesting_level) {
@ -467,14 +466,14 @@ acpi_ut_status_exit(u32 line_number,
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name,
module_name, component_id, "%s %s\n",
acpi_gbl_fn_exit_str,
acpi_gbl_function_exit_prefix,
acpi_format_exception(status));
} else {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name,
module_name, component_id,
"%s ****Exception****: %s\n",
acpi_gbl_fn_exit_str,
acpi_gbl_function_exit_prefix,
acpi_format_exception(status));
}
}
@ -514,7 +513,7 @@ acpi_ut_value_exit(u32 line_number,
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s %8.8X%8.8X\n",
acpi_gbl_fn_exit_str,
acpi_gbl_function_exit_prefix,
ACPI_FORMAT_UINT64(value));
}
@ -552,8 +551,8 @@ acpi_ut_ptr_exit(u32 line_number,
if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
acpi_debug_print(ACPI_LV_FUNCTIONS,
line_number, function_name, module_name,
component_id, "%s %p\n", acpi_gbl_fn_exit_str,
ptr);
component_id, "%s %p\n",
acpi_gbl_function_exit_prefix, ptr);
}
if (acpi_gbl_nesting_level) {

View File

@ -446,7 +446,7 @@ const char *acpi_ut_get_mutex_name(u32 mutex_id)
/* Names for Notify() values, used for debug output */
static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
static const char *acpi_gbl_generic_notify[ACPI_GENERIC_NOTIFY_MAX + 1] = {
/* 00 */ "Bus Check",
/* 01 */ "Device Check",
/* 02 */ "Device Wake",
@ -460,48 +460,52 @@ static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
/* 0A */ "Reserved",
/* 0B */ "System Locality Update",
/* 0C */ "Shutdown Request",
/* Reserved in ACPI 6.0 */
/* 0D */ "System Resource Affinity Update"
};
static const char *acpi_gbl_device_notify[4] = {
static const char *acpi_gbl_device_notify[5] = {
/* 80 */ "Status Change",
/* 81 */ "Information Change",
/* 82 */ "Device-Specific Change",
/* 83 */ "Device-Specific Change"
/* 83 */ "Device-Specific Change",
/* 84 */ "Reserved"
};
static const char *acpi_gbl_processor_notify[4] = {
static const char *acpi_gbl_processor_notify[5] = {
/* 80 */ "Performance Capability Change",
/* 81 */ "C-State Change",
/* 82 */ "Throttling Capability Change",
/* 83 */ "Device-Specific Change"
/* 83 */ "Guaranteed Change",
/* 84 */ "Minimum Excursion"
};
static const char *acpi_gbl_thermal_notify[4] = {
static const char *acpi_gbl_thermal_notify[5] = {
/* 80 */ "Thermal Status Change",
/* 81 */ "Thermal Trip Point Change",
/* 82 */ "Thermal Device List Change",
/* 83 */ "Thermal Relationship Change"
/* 83 */ "Thermal Relationship Change",
/* 84 */ "Reserved"
};
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
{
/* 00 - 0D are common to all object types */
/* 00 - 0D are "common to all object types" (from ACPI Spec) */
if (notify_value <= ACPI_NOTIFY_MAX) {
if (notify_value <= ACPI_GENERIC_NOTIFY_MAX) {
return (acpi_gbl_generic_notify[notify_value]);
}
/* 0D - 7F are reserved */
/* 0E - 7F are reserved */
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
}
/* 80 - 83 are per-object-type */
/* 80 - 84 are per-object-type */
if (notify_value <= 0x83) {
if (notify_value <= ACPI_SPECIFIC_NOTIFY_MAX) {
switch (type) {
case ACPI_TYPE_ANY:
case ACPI_TYPE_DEVICE:

View File

@ -69,7 +69,7 @@ ACPI_MODULE_NAME("uteval")
acpi_status
acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
char *path,
const char *path,
u32 expected_return_btypes,
union acpi_operand_object **return_desc)
{
@ -204,7 +204,7 @@ cleanup:
******************************************************************************/
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
acpi_ut_evaluate_numeric_object(const char *object_name,
struct acpi_namespace_node *device_node,
u64 *value)
{

View File

@ -80,6 +80,11 @@ const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = {
"_S4D"
};
/* Hex-to-ascii */
const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
/*******************************************************************************
*
* Namespace globals
@ -221,6 +226,49 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
};
#endif /* !ACPI_REDUCED_HARDWARE */
#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER)
/* to_pld macro: compile/disassemble strings */
const char *acpi_gbl_pld_panel_list[] = {
"TOP",
"BOTTOM",
"LEFT",
"RIGHT",
"FRONT",
"BACK",
"UNKNOWN",
NULL
};
const char *acpi_gbl_pld_vertical_position_list[] = {
"UPPER",
"CENTER",
"LOWER",
NULL
};
const char *acpi_gbl_pld_horizontal_position_list[] = {
"LEFT",
"CENTER",
"RIGHT",
NULL
};
const char *acpi_gbl_pld_shape_list[] = {
"ROUND",
"OVAL",
"SQUARE",
"VERTICALRECTANGLE",
"HORIZONTALRECTANGLE",
"VERTICALTRAPEZOID",
"HORIZONTALTRAPEZOID",
"UNKNOWN",
"CHAMFERED",
NULL
};
#endif
/* Public globals */
ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)

View File

@ -361,7 +361,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
void
acpi_ut_display_init_pathname(u8 type,
struct acpi_namespace_node *obj_handle,
char *path)
const char *path)
{
acpi_status status;
struct acpi_buffer buffer;

View File

@ -206,36 +206,40 @@ acpi_ut_safe_strncat(char *dest,
* FUNCTION: acpi_ut_strtoul64
*
* PARAMETERS: string - Null terminated string
* base - Radix of the string: 16 or ACPI_ANY_BASE;
* ACPI_ANY_BASE means 'in behalf of to_integer'
* ret_integer - Where the converted integer is returned
* base - Radix of the string: 16 or 10 or
* ACPI_ANY_BASE
* max_integer_byte_width - Maximum allowable integer,in bytes:
* 4 or 8 (32 or 64 bits)
* ret_integer - Where the converted integer is
* returned
*
* RETURN: Status and Converted value
*
* DESCRIPTION: Convert a string into an unsigned value. Performs either a
* 32-bit or 64-bit conversion, depending on the current mode
* of the interpreter.
* 32-bit or 64-bit conversion, depending on the input integer
* size (often the current mode of the interpreter).
*
* NOTES: acpi_gbl_integer_byte_width should be set to the proper width.
* NOTES: Negative numbers are not supported, as they are not supported
* by ACPI.
*
* acpi_gbl_integer_byte_width should be set to the proper width.
* For the core ACPICA code, this width depends on the DSDT
* version. For iASL, the default byte width is always 8.
* version. For iASL, the default byte width is always 8 for the
* parser, but error checking is performed later to flag cases
* where a 64-bit constant is defined in a 32-bit DSDT/SSDT.
*
* Does not support Octal strings, not needed at this time.
*
* There is an earlier version of the function after this one,
* below. It is slightly different than this one, and the two
* may eventually may need to be merged. (01/2016).
*
******************************************************************************/
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
acpi_status
acpi_ut_strtoul64(char *string,
u32 base, u32 max_integer_byte_width, u64 *ret_integer)
{
u32 this_digit = 0;
u64 return_value = 0;
u64 quotient;
u64 dividend;
u32 to_integer_op = (base == ACPI_ANY_BASE);
u32 mode32 = (acpi_gbl_integer_byte_width == 4);
u8 valid_digits = 0;
u8 sign_of0x = 0;
u8 term = 0;
@ -244,6 +248,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
switch (base) {
case ACPI_ANY_BASE:
case 10:
case 16:
break;
@ -265,9 +270,9 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
string++;
}
if (to_integer_op) {
if (base == ACPI_ANY_BASE) {
/*
* Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
* Base equal to ACPI_ANY_BASE means 'Either decimal or hex'.
* We need to determine if it is decimal or hexadecimal.
*/
if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) {
@ -284,7 +289,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
/* Any string left? Check that '0x' is not followed by white space. */
if (!(*string) || isspace((int)*string) || *string == '\t') {
if (to_integer_op) {
if (base == ACPI_ANY_BASE) {
goto error_exit;
} else {
goto all_done;
@ -292,10 +297,11 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
}
/*
* Perform a 32-bit or 64-bit conversion, depending upon the current
* execution mode of the interpreter
* Perform a 32-bit or 64-bit conversion, depending upon the input
* byte width
*/
dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
dividend = (max_integer_byte_width <= ACPI_MAX32_BYTE_WIDTH) ?
ACPI_UINT32_MAX : ACPI_UINT64_MAX;
/* Main loop: convert the string to a 32- or 64-bit integer */
@ -323,7 +329,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
}
if (term) {
if (to_integer_op) {
if (base == ACPI_ANY_BASE) {
goto error_exit;
} else {
break;
@ -338,12 +344,13 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
valid_digits++;
if (sign_of0x
&& ((valid_digits > 16)
|| ((valid_digits > 8) && mode32))) {
if (sign_of0x && ((valid_digits > 16) ||
((valid_digits > 8)
&& (max_integer_byte_width <=
ACPI_MAX32_BYTE_WIDTH)))) {
/*
* This is to_integer operation case.
* No any restrictions for string-to-integer conversion,
* No restrictions for string-to-integer conversion,
* see ACPI spec.
*/
goto error_exit;
@ -355,7 +362,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
&quotient, NULL);
if (return_value > quotient) {
if (to_integer_op) {
if (base == ACPI_ANY_BASE) {
goto error_exit;
} else {
break;
@ -378,7 +385,8 @@ all_done:
return_ACPI_STATUS(AE_OK);
error_exit:
/* Base was set/validated above */
/* Base was set/validated above (10 or 16) */
if (base == 10) {
return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
@ -388,8 +396,7 @@ error_exit:
}
#ifdef _OBSOLETE_FUNCTIONS
/* TBD: use version in ACPICA main code base? */
/* DONE: 01/2016 */
/* Removed: 01/2016 */
/*******************************************************************************
*

View File

@ -67,11 +67,6 @@ static char *acpi_ut_format_number(char *string,
static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
/* Module globals */
static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
/*******************************************************************************
*
* FUNCTION: acpi_ut_bound_string_length

View File

@ -143,73 +143,6 @@ void acpi_ut_print_string(char *string, u16 max_length)
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_char
*
* PARAMETERS: char - The character to be examined
* position - Byte position (0-3)
*
* RETURN: TRUE if the character is valid, FALSE otherwise
*
* DESCRIPTION: Check for a valid ACPI character. Must be one of:
* 1) Upper case alpha
* 2) numeric
* 3) underscore
*
* We allow a '!' as the last character because of the ASF! table
*
******************************************************************************/
u8 acpi_ut_valid_acpi_char(char character, u32 position)
{
if (!((character >= 'A' && character <= 'Z') ||
(character >= '0' && character <= '9') || (character == '_'))) {
/* Allow a '!' in the last position */
if (character == '!' && position == 3) {
return (TRUE);
}
return (FALSE);
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_name
*
* PARAMETERS: name - The name to be examined. Does not have to
* be NULL terminated string.
*
* RETURN: TRUE if the name is valid, FALSE otherwise
*
* DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
* 1) Upper case alpha
* 2) numeric
* 3) underscore
*
******************************************************************************/
u8 acpi_ut_valid_acpi_name(char *name)
{
u32 i;
ACPI_FUNCTION_ENTRY();
for (i = 0; i < ACPI_NAME_SIZE; i++) {
if (!acpi_ut_valid_acpi_char(name[i], i)) {
return (FALSE);
}
}
return (TRUE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_repair_name
@ -253,7 +186,7 @@ void acpi_ut_repair_name(char *name)
/* Check each character in the name */
for (i = 0; i < ACPI_NAME_SIZE; i++) {
if (acpi_ut_valid_acpi_char(name[i], i)) {
if (acpi_ut_valid_name_char(name[i], i)) {
continue;
}

View File

@ -90,7 +90,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
******************************************************************************/
acpi_status
acpi_ut_create_list(char *list_name,
acpi_ut_create_list(const char *list_name,
u16 object_size, struct acpi_memory_list **return_cache)
{
struct acpi_memory_list *cache;

View File

@ -3,7 +3,7 @@
*
* Check to see if the given machine has a known bad ACPI BIOS
* or if the BIOS is too old.
* Check given machine against acpi_osi_dmi_table[].
* Check given machine against acpi_rev_dmi_table[].
*
* Copyright (C) 2004 Len Brown <len.brown@intel.com>
* Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
@ -47,7 +47,7 @@ struct acpi_blacklist_item {
u32 is_critical_error;
};
static struct dmi_system_id acpi_osi_dmi_table[] __initdata;
static struct dmi_system_id acpi_rev_dmi_table[] __initdata;
/*
* POLICY: If *anything* doesn't work, put it on the blacklist.
@ -128,36 +128,12 @@ int __init acpi_blacklisted(void)
}
}
dmi_check_system(acpi_osi_dmi_table);
(void)early_acpi_osi_init();
dmi_check_system(acpi_rev_dmi_table);
return blacklisted;
}
#ifdef CONFIG_DMI
static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
{
acpi_dmi_osi_linux(1, d); /* enable */
return 0;
}
static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2006");
acpi_osi_setup("!Windows 2006 SP1");
acpi_osi_setup("!Windows 2006 SP2");
return 0;
}
static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2009");
return 0;
}
static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2012");
return 0;
}
#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
static int __init dmi_enable_rev_override(const struct dmi_system_id *d)
{
@ -168,169 +144,7 @@ static int __init dmi_enable_rev_override(const struct dmi_system_id *d)
}
#endif
static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
{
.callback = dmi_disable_osi_vista,
.ident = "Fujitsu Siemens",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
},
},
{
/*
* There have a NVIF method in MSI GX723 DSDT need call by Nvidia
* driver (e.g. nouveau) when user press brightness hotkey.
* Currently, nouveau driver didn't do the job and it causes there
* have a infinite while loop in DSDT when user press hotkey.
* We add MSI GX723's dmi information to this table for workaround
* this issue.
* Will remove MSI GX723 from the table after nouveau grows support.
*/
.callback = dmi_disable_osi_vista,
.ident = "MSI GX723",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-NS10J_S",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-SR290J",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "VGN-NS50B_L",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "VGN-SR19XN",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba Satellite L355",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
},
},
{
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba P305D",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba NB100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
},
},
/*
* The wireless hotkey does not work on those machines when
* returning true for _OSI("Windows 2012")
*/
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 7737",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 7537",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 5437",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 3437",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Vostro 3446",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Vostro 3546",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
},
},
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
* Linux ignores it, except for the machines enumerated below.
*/
/*
* Without this this EEEpc exports a non working WMI interface, with
* this it exports a working "good old" eeepc_laptop interface, fixing
* both brightness control, and rfkill not working.
*/
{
.callback = dmi_enable_osi_linux,
.ident = "Asus EEE PC 1015PX",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
},
},
static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
#ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
/*
* DELL XPS 13 (2015) switches sound between HDA and I2S

View File

@ -925,12 +925,14 @@ void __init acpi_early_init(void)
goto error0;
}
if (acpi_gbl_group_module_level_code) {
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
"Unable to load the System Description Tables\n");
goto error0;
}
}
#ifdef CONFIG_X86
if (!acpi_ioapic) {
@ -995,17 +997,10 @@ static int __init acpi_bus_init(void)
acpi_os_initialize1();
status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
"Unable to start the ACPI Interpreter\n");
goto error1;
}
/*
* ACPI 2.0 requires the EC driver to be loaded and work before
* the EC device is found in the namespace (i.e. before acpi_initialize_objects()
* is called).
* the EC device is found in the namespace (i.e. before
* acpi_load_tables() is called).
*
* This is accomplished by looking for the ECDT table, and getting
* the EC parameters out of that.
@ -1013,6 +1008,22 @@ static int __init acpi_bus_init(void)
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
if (!acpi_gbl_group_module_level_code) {
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
"Unable to load the System Description Tables\n");
goto error1;
}
}
status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
"Unable to start the ACPI Interpreter\n");
goto error1;
}
status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");

View File

@ -333,7 +333,8 @@ int acpi_device_modalias(struct device *dev, char *buf, int size)
EXPORT_SYMBOL_GPL(acpi_device_modalias);
static ssize_t
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
@ -397,7 +398,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
static ssize_t
acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
@ -467,12 +469,27 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
if (ACPI_FAILURE(status))
return -ENODEV;
return -EIO;
return sprintf(buf, "%llu\n", sun);
}
static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
static ssize_t
acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
char *buf) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
acpi_status status;
unsigned long long hrv;
status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv);
if (ACPI_FAILURE(status))
return -EIO;
return sprintf(buf, "%llu\n", hrv);
}
static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL);
static ssize_t status_show(struct device *dev, struct device_attribute *attr,
char *buf) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
@ -481,7 +498,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
return -EIO;
return sprintf(buf, "%llu\n", sta);
}
@ -541,6 +558,12 @@ int acpi_device_setup_files(struct acpi_device *dev)
goto end;
}
if (acpi_has_method(dev->handle, "_HRV")) {
result = device_create_file(&dev->dev, &dev_attr_hrv);
if (result)
goto end;
}
if (acpi_has_method(dev->handle, "_STA")) {
result = device_create_file(&dev->dev, &dev_attr_status);
if (result)
@ -604,6 +627,9 @@ void acpi_device_remove_files(struct acpi_device *dev)
if (acpi_has_method(dev->handle, "_SUN"))
device_remove_file(&dev->dev, &dev_attr_sun);
if (acpi_has_method(dev->handle, "_HRV"))
device_remove_file(&dev->dev, &dev_attr_hrv);
if (dev->pnp.unique_id)
device_remove_file(&dev->dev, &dev_attr_uid);
if (dev->pnp.type.bus_address)

View File

@ -105,8 +105,8 @@ enum ec_command {
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */
EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
* OpReg are installed */
EC_FLAGS_GPE_HANDLER_INSTALLED, /* GPE handler installed */
EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */
EC_FLAGS_STARTED, /* Driver is started */
EC_FLAGS_STOPPED, /* Driver is stopped */
EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the
@ -175,10 +175,9 @@ static void acpi_ec_event_processor(struct work_struct *work);
struct acpi_ec *boot_ec, *first_ec;
EXPORT_SYMBOL(first_ec);
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
/* --------------------------------------------------------------------------
* Logging/Debugging
@ -367,7 +366,8 @@ static inline void acpi_ec_clear_gpe(struct acpi_ec *ec)
static void acpi_ec_submit_request(struct acpi_ec *ec)
{
ec->reference_count++;
if (ec->reference_count == 1)
if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
ec->reference_count == 1)
acpi_ec_enable_gpe(ec, true);
}
@ -376,7 +376,8 @@ static void acpi_ec_complete_request(struct acpi_ec *ec)
bool flushed = false;
ec->reference_count--;
if (ec->reference_count == 0)
if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
ec->reference_count == 0)
acpi_ec_disable_gpe(ec, true);
flushed = acpi_ec_flushed(ec);
if (flushed)
@ -1287,15 +1288,9 @@ static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status;
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
return 0;
status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status))
return -ENODEV;
acpi_ec_start(ec, false);
if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
@ -1303,36 +1298,54 @@ static int ec_install_handlers(struct acpi_ec *ec)
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
/*
* Maybe OS fails in evaluating the _REG object.
* The AE_NOT_FOUND error will be ignored and OS
* continue to initialize EC.
* Maybe OS fails in evaluating the _REG
* object. The AE_NOT_FOUND error will be
* ignored and OS * continue to initialize
* EC.
*/
pr_err("Fail in evaluating the _REG object"
" of EC device. Broken bios is suspected.\n");
} else {
acpi_ec_stop(ec, false);
acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler);
return -ENODEV;
}
}
set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
}
if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec);
/* This is not fatal as we can poll EC events */
if (ACPI_SUCCESS(status)) {
set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
ec->reference_count >= 1)
acpi_ec_enable_gpe(ec, true);
}
}
set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
return 0;
}
static void ec_remove_handlers(struct acpi_ec *ec)
{
if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
return;
acpi_ec_stop(ec, false);
if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err("failed to remove space handler\n");
clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
}
if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
pr_err("failed to remove gpe handler\n");
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
clear_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
}
}
static int acpi_ec_add(struct acpi_device *device)
@ -1344,11 +1357,12 @@ static int acpi_ec_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
/* Check for boot EC */
if (boot_ec &&
(boot_ec->handle == device->handle ||
boot_ec->handle == ACPI_ROOT_OBJECT)) {
if (boot_ec) {
ec = boot_ec;
boot_ec = NULL;
ec_remove_handlers(ec);
if (first_ec == ec)
first_ec = NULL;
} else {
ec = make_acpi_ec();
if (!ec)
@ -1434,7 +1448,7 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
int __init acpi_boot_ec_enable(void)
{
if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
if (!boot_ec)
return 0;
if (!ec_install_handlers(boot_ec)) {
first_ec = boot_ec;
@ -1448,20 +1462,6 @@ static const struct acpi_device_id ec_device_ids[] = {
{"", 0},
};
/* Some BIOS do not survive early DSDT scan, skip it */
static int ec_skip_dsdt_scan(const struct dmi_system_id *id)
{
EC_FLAGS_SKIP_DSDT_SCAN = 1;
return 0;
}
/* ASUStek often supplies us with broken ECDT, validate it */
static int ec_validate_ecdt(const struct dmi_system_id *id)
{
EC_FLAGS_VALIDATE_ECDT = 1;
return 0;
}
#if 0
/*
* Some EC firmware variations refuses to respond QR_EC when SCI_EVT is not
@ -1503,30 +1503,29 @@ static int ec_clear_on_resume(const struct dmi_system_id *id)
return 0;
}
static int ec_correct_ecdt(const struct dmi_system_id *id)
{
pr_debug("Detected system needing ECDT address correction.\n");
EC_FLAGS_CORRECT_ECDT = 1;
return 0;
}
static struct dmi_system_id ec_dmi_table[] __initdata = {
{
ec_skip_dsdt_scan, "Compal JFL92", {
DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
ec_correct_ecdt, "Asus L4R", {
DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
{
ec_validate_ecdt, "MSI MS-171F", {
ec_correct_ecdt, "Asus M6R", {
DMI_MATCH(DMI_BIOS_VERSION, "0207"),
DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
{
ec_correct_ecdt, "MSI MS-171F", {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL},
{
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
{
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
{
ec_skip_dsdt_scan, "HP Folio 13", {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL},
{
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
{
ec_clear_on_resume, "Samsung hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{},
@ -1534,8 +1533,8 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
int __init acpi_ec_ecdt_probe(void)
{
int ret = 0;
acpi_status status;
struct acpi_ec *saved_ec = NULL;
struct acpi_table_ecdt *ecdt_ptr;
boot_ec = make_acpi_ec();
@ -1547,67 +1546,45 @@ int __init acpi_ec_ecdt_probe(void)
dmi_check_system(ec_dmi_table);
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
if (ACPI_FAILURE(status)) {
ret = -ENODEV;
goto error;
}
if (!ecdt_ptr->control.address || !ecdt_ptr->data.address) {
/*
* Asus X50GL:
* https://bugzilla.kernel.org/show_bug.cgi?id=11880
*/
ret = -ENODEV;
goto error;
}
pr_info("EC description table is found, configuring boot EC\n");
if (EC_FLAGS_CORRECT_ECDT) {
/*
* Asus L4R, Asus M6R
* https://bugzilla.kernel.org/show_bug.cgi?id=9399
* MSI MS-171F
* https://bugzilla.kernel.org/show_bug.cgi?id=12461
*/
boot_ec->command_addr = ecdt_ptr->data.address;
boot_ec->data_addr = ecdt_ptr->control.address;
} else {
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
}
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
&boot_ec->handle);
/* Don't trust ECDT, which comes from ASUSTek */
if (!EC_FLAGS_VALIDATE_ECDT)
goto install;
saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL);
if (!saved_ec)
return -ENOMEM;
/* fall through */
}
if (EC_FLAGS_SKIP_DSDT_SCAN) {
kfree(saved_ec);
return -ENODEV;
}
/* This workaround is needed only on some broken machines,
* which require early EC, but fail to provide ECDT */
pr_debug("Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL);
/* Check that acpi_get_devices actually find something */
if (ACPI_FAILURE(status) || !boot_ec->handle)
goto error;
if (saved_ec) {
/* try to find good ECDT from ASUSTek */
if (saved_ec->command_addr != boot_ec->command_addr ||
saved_ec->data_addr != boot_ec->data_addr ||
saved_ec->gpe != boot_ec->gpe ||
saved_ec->handle != boot_ec->handle)
pr_info("ASUSTek keeps feeding us with broken "
"ECDT tables, which are very hard to workaround. "
"Trying to use DSDT EC info instead. Please send "
"output of acpidump to linux-acpi@vger.kernel.org\n");
kfree(saved_ec);
saved_ec = NULL;
} else {
/* We really need to limit this workaround, the only ASUS,
* which needs it, has fake EC._INI method, so use it as flag.
* Keep boot_ec struct as it will be needed soon.
*/
if (!dmi_name_in_vendors("ASUS") ||
!acpi_has_method(boot_ec->handle, "_INI"))
return -ENODEV;
}
install:
if (!ec_install_handlers(boot_ec)) {
ret = ec_install_handlers(boot_ec);
if (!ret)
first_ec = boot_ec;
return 0;
}
error:
if (ret) {
kfree(boot_ec);
kfree(saved_ec);
boot_ec = NULL;
return -ENODEV;
}
return ret;
}
static int param_set_event_clearing(const char *val, struct kernel_param *kp)

154
drivers/acpi/evged.c Normal file
View File

@ -0,0 +1,154 @@
/*
* Generic Event Device for ACPI.
*
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Generic Event Device allows platforms to handle interrupts in ACPI
* ASL statements. It follows very similar to _EVT method approach
* from GPIO events. All interrupts are listed in _CRS and the handler
* is written in _EVT method. Here is an example.
*
* Device (GED0)
* {
*
* Name (_HID, "ACPI0013")
* Name (_UID, 0)
* Method (_CRS, 0x0, Serialized)
* {
* Name (RBUF, ResourceTemplate ()
* {
* Interrupt(ResourceConsumer, Edge, ActiveHigh, Shared, , , )
* {123}
* }
* })
*
* Method (_EVT, 1) {
* if (Lequal(123, Arg0))
* {
* }
* }
* }
*
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#define MODULE_NAME "acpi-ged"
struct acpi_ged_event {
struct list_head node;
struct device *dev;
unsigned int gsi;
unsigned int irq;
acpi_handle handle;
};
static irqreturn_t acpi_ged_irq_handler(int irq, void *data)
{
struct acpi_ged_event *event = data;
acpi_status acpi_ret;
acpi_ret = acpi_execute_simple_method(event->handle, NULL, event->gsi);
if (ACPI_FAILURE(acpi_ret))
dev_err_once(event->dev, "IRQ method execution failed\n");
return IRQ_HANDLED;
}
static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
void *context)
{
struct acpi_ged_event *event;
unsigned int irq;
unsigned int gsi;
unsigned int irqflags = IRQF_ONESHOT;
struct device *dev = context;
acpi_handle handle = ACPI_HANDLE(dev);
acpi_handle evt_handle;
struct resource r;
struct acpi_resource_irq *p = &ares->data.irq;
struct acpi_resource_extended_irq *pext = &ares->data.extended_irq;
if (ares->type == ACPI_RESOURCE_TYPE_END_TAG)
return AE_OK;
if (!acpi_dev_resource_interrupt(ares, 0, &r)) {
dev_err(dev, "unable to parse IRQ resource\n");
return AE_ERROR;
}
if (ares->type == ACPI_RESOURCE_TYPE_IRQ)
gsi = p->interrupts[0];
else
gsi = pext->interrupts[0];
irq = r.start;
if (ACPI_FAILURE(acpi_get_handle(handle, "_EVT", &evt_handle))) {
dev_err(dev, "cannot locate _EVT method\n");
return AE_ERROR;
}
dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL);
if (!event)
return AE_ERROR;
event->gsi = gsi;
event->dev = dev;
event->irq = irq;
event->handle = evt_handle;
if (r.flags & IORESOURCE_IRQ_SHAREABLE)
irqflags |= IRQF_SHARED;
if (devm_request_threaded_irq(dev, irq, NULL, acpi_ged_irq_handler,
irqflags, "ACPI:Ged", event)) {
dev_err(dev, "failed to setup event handler for irq %u\n", irq);
return AE_ERROR;
}
return AE_OK;
}
static int ged_probe(struct platform_device *pdev)
{
acpi_status acpi_ret;
acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS",
acpi_ged_request_interrupt, &pdev->dev);
if (ACPI_FAILURE(acpi_ret)) {
dev_err(&pdev->dev, "unable to parse the _CRS record\n");
return -EINVAL;
}
return 0;
}
static const struct acpi_device_id ged_acpi_ids[] = {
{"ACPI0013"},
{},
};
static struct platform_driver ged_driver = {
.probe = ged_probe,
.driver = {
.name = MODULE_NAME,
.acpi_match_table = ACPI_PTR(ged_acpi_ids),
},
};
builtin_platform_driver(ged_driver);

View File

@ -20,7 +20,8 @@
#define PREFIX "ACPI: "
void acpi_initrd_initialize_tables(void);
int early_acpi_osi_init(void);
int acpi_osi_init(void);
acpi_status acpi_os_initialize1(void);
void init_acpi_device_notify(void);
int acpi_scan_init(void);

View File

@ -327,10 +327,18 @@ int __init acpi_numa_init(void)
/* SRAT: Static Resource Affinity Table */
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
acpi_parse_x2apic_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, 0);
struct acpi_subtable_proc srat_proc[2];
memset(srat_proc, 0, sizeof(srat_proc));
srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
srat_proc[0].handler = acpi_parse_processor_affinity;
srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
srat_proc[1].handler = acpi_parse_x2apic_affinity;
acpi_table_parse_entries_array(ACPI_SIG_SRAT,
sizeof(struct acpi_table_srat),
srat_proc, ARRAY_SIZE(srat_proc), 0);
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity,
NR_NODE_MEMBLKS);

522
drivers/acpi/osi.c Normal file
View File

@ -0,0 +1,522 @@
/*
* osi.c - _OSI implementation
*
* Copyright (C) 2016 Intel Corporation
* Author: Lv Zheng <lv.zheng@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* Uncomment next line to get verbose printout */
/* #define DEBUG */
#define pr_fmt(fmt) "ACPI: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include "internal.h"
#define OSI_STRING_LENGTH_MAX 64
#define OSI_STRING_ENTRIES_MAX 16
struct acpi_osi_entry {
char string[OSI_STRING_LENGTH_MAX];
bool enable;
};
static struct acpi_osi_config {
u8 default_disabling;
unsigned int linux_enable:1;
unsigned int linux_dmi:1;
unsigned int linux_cmdline:1;
unsigned int darwin_enable:1;
unsigned int darwin_dmi:1;
unsigned int darwin_cmdline:1;
} osi_config;
static struct acpi_osi_config osi_config;
static struct acpi_osi_entry
osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
{"Module Device", true},
{"Processor Device", true},
{"3.0 _SCP Extensions", true},
{"Processor Aggregator Device", true},
};
static u32 acpi_osi_handler(acpi_string interface, u32 supported)
{
if (!strcmp("Linux", interface)) {
pr_notice_once(FW_BUG
"BIOS _OSI(Linux) query %s%s\n",
osi_config.linux_enable ? "honored" : "ignored",
osi_config.linux_cmdline ? " via cmdline" :
osi_config.linux_dmi ? " via DMI" : "");
}
if (!strcmp("Darwin", interface)) {
pr_notice_once(
"BIOS _OSI(Darwin) query %s%s\n",
osi_config.darwin_enable ? "honored" : "ignored",
osi_config.darwin_cmdline ? " via cmdline" :
osi_config.darwin_dmi ? " via DMI" : "");
}
return supported;
}
void __init acpi_osi_setup(char *str)
{
struct acpi_osi_entry *osi;
bool enable = true;
int i;
if (!acpi_gbl_create_osi_method)
return;
if (str == NULL || *str == '\0') {
pr_info("_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
return;
}
if (*str == '!') {
str++;
if (*str == '\0') {
/* Do not override acpi_osi=!* */
if (!osi_config.default_disabling)
osi_config.default_disabling =
ACPI_DISABLE_ALL_VENDOR_STRINGS;
return;
} else if (*str == '*') {
osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS;
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
osi->enable = false;
}
return;
} else if (*str == '!') {
osi_config.default_disabling = 0;
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 __acpi_osi_setup_darwin(bool enable)
{
osi_config.darwin_enable = !!enable;
if (enable) {
acpi_osi_setup("!");
acpi_osi_setup("Darwin");
} else {
acpi_osi_setup("!!");
acpi_osi_setup("!Darwin");
}
}
static void __init acpi_osi_setup_darwin(bool enable)
{
/* Override acpi_osi_dmi_blacklisted() */
osi_config.darwin_dmi = 0;
osi_config.darwin_cmdline = 1;
__acpi_osi_setup_darwin(enable);
}
/*
* The story of _OSI(Linux)
*
* From pre-history through Linux-2.6.22, Linux responded TRUE upon a BIOS
* OSI(Linux) query.
*
* Unfortunately, reference BIOS writers got wind of this and put
* OSI(Linux) in their example code, quickly exposing this string as
* ill-conceived and opening the door to an un-bounded number of BIOS
* incompatibilities.
*
* For example, OSI(Linux) was used on resume to re-POST a video card on
* one system, because Linux at that time could not do a speedy restore in
* its native driver. But then upon gaining quick native restore
* capability, Linux has no way to tell the BIOS to skip the time-consuming
* POST -- putting Linux at a permanent performance disadvantage. On
* another system, the BIOS writer used OSI(Linux) to infer native OS
* support for IPMI! On other systems, OSI(Linux) simply got in the way of
* Linux claiming to be compatible with other operating systems, exposing
* BIOS issues such as skipped device initialization.
*
* So "Linux" turned out to be a really poor chose of OSI string, and from
* Linux-2.6.23 onward we respond FALSE.
*
* BIOS writers should NOT query _OSI(Linux) on future systems. Linux will
* complain on the console when it sees it, and return FALSE. To get Linux
* to return TRUE for your system will require a kernel source update to
* add a DMI entry, or boot with "acpi_osi=Linux"
*/
static void __init __acpi_osi_setup_linux(bool enable)
{
osi_config.linux_enable = !!enable;
if (enable)
acpi_osi_setup("Linux");
else
acpi_osi_setup("!Linux");
}
static void __init acpi_osi_setup_linux(bool enable)
{
/* Override acpi_osi_dmi_blacklisted() */
osi_config.linux_dmi = 0;
osi_config.linux_cmdline = 1;
__acpi_osi_setup_linux(enable);
}
/*
* Modify the list of "OS Interfaces" reported to BIOS via _OSI
*
* empty string disables _OSI
* string starting with '!' disables that string
* otherwise string is added to list, augmenting built-in strings
*/
static void __init acpi_osi_setup_late(void)
{
struct acpi_osi_entry *osi;
char *str;
int i;
acpi_status status;
if (osi_config.default_disabling) {
status = acpi_update_interfaces(osi_config.default_disabling);
if (ACPI_SUCCESS(status))
pr_info("Disabled all _OSI OS vendors%s\n",
osi_config.default_disabling ==
ACPI_DISABLE_ALL_STRINGS ?
" and feature groups" : "");
}
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
str = osi->string;
if (*str == '\0')
break;
if (osi->enable) {
status = acpi_install_interface(str);
if (ACPI_SUCCESS(status))
pr_info("Added _OSI(%s)\n", str);
} else {
status = acpi_remove_interface(str);
if (ACPI_SUCCESS(status))
pr_info("Deleted _OSI(%s)\n", str);
}
}
}
static int __init osi_setup(char *str)
{
if (str && !strcmp("Linux", str))
acpi_osi_setup_linux(true);
else if (str && !strcmp("!Linux", str))
acpi_osi_setup_linux(false);
else if (str && !strcmp("Darwin", str))
acpi_osi_setup_darwin(true);
else if (str && !strcmp("!Darwin", str))
acpi_osi_setup_darwin(false);
else
acpi_osi_setup(str);
return 1;
}
__setup("acpi_osi=", osi_setup);
bool acpi_osi_is_win8(void)
{
return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
}
EXPORT_SYMBOL(acpi_osi_is_win8);
static void __init acpi_osi_dmi_darwin(bool enable,
const struct dmi_system_id *d)
{
pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident);
osi_config.darwin_dmi = 1;
__acpi_osi_setup_darwin(enable);
}
void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d)
{
pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
osi_config.linux_dmi = 1;
__acpi_osi_setup_linux(enable);
}
static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d)
{
acpi_osi_dmi_darwin(true, d);
return 0;
}
static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
{
acpi_osi_dmi_linux(true, d);
return 0;
}
static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
{
pr_notice("DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2006");
acpi_osi_setup("!Windows 2006 SP1");
acpi_osi_setup("!Windows 2006 SP2");
return 0;
}
static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
{
pr_notice("DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2009");
return 0;
}
static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
{
pr_notice("DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2012");
return 0;
}
/*
* Linux default _OSI response behavior is determined by this DMI table.
*
* Note that _OSI("Linux")/_OSI("Darwin") determined here can be overridden
* by acpi_osi=!Linux/acpi_osi=!Darwin command line options.
*/
static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
{
.callback = dmi_disable_osi_vista,
.ident = "Fujitsu Siemens",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
},
},
{
/*
* There have a NVIF method in MSI GX723 DSDT need call by Nvidia
* driver (e.g. nouveau) when user press brightness hotkey.
* Currently, nouveau driver didn't do the job and it causes there
* have a infinite while loop in DSDT when user press hotkey.
* We add MSI GX723's dmi information to this table for workaround
* this issue.
* Will remove MSI GX723 from the table after nouveau grows support.
*/
.callback = dmi_disable_osi_vista,
.ident = "MSI GX723",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-NS10J_S",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-SR290J",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "VGN-NS50B_L",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "VGN-SR19XN",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba Satellite L355",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
},
},
{
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba P305D",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "Toshiba NB100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
},
},
/*
* The wireless hotkey does not work on those machines when
* returning true for _OSI("Windows 2012")
*/
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 7737",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 7537",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 5437",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 3437",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Vostro 3446",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Vostro 3546",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
},
},
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
* Linux ignores it, except for the machines enumerated below.
*/
/*
* Without this this EEEpc exports a non working WMI interface, with
* this it exports a working "good old" eeepc_laptop interface, fixing
* both brightness control, and rfkill not working.
*/
{
.callback = dmi_enable_osi_linux,
.ident = "Asus EEE PC 1015PX",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
},
},
/*
* Enable _OSI("Darwin") for all apple platforms.
*/
{
.callback = dmi_enable_osi_darwin,
.ident = "Apple hardware",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
},
},
{
.callback = dmi_enable_osi_darwin,
.ident = "Apple hardware",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
},
},
{}
};
static __init void acpi_osi_dmi_blacklisted(void)
{
dmi_check_system(acpi_osi_dmi_table);
}
int __init early_acpi_osi_init(void)
{
acpi_osi_dmi_blacklisted();
return 0;
}
int __init acpi_osi_init(void)
{
acpi_install_interface_handler(acpi_osi_handler);
acpi_osi_setup_late();
return 0;
}

View File

@ -56,10 +56,6 @@ struct acpi_os_dpc {
struct work_struct work;
};
#ifdef CONFIG_ACPI_CUSTOM_DSDT
#include CONFIG_ACPI_CUSTOM_DSDT_FILE
#endif
#ifdef ENABLE_DEBUGGER
#include <linux/kdb.h>
@ -96,72 +92,6 @@ struct acpi_ioremap {
static LIST_HEAD(acpi_ioremaps);
static DEFINE_MUTEX(acpi_ioremap_lock);
static void __init acpi_osi_setup_late(void);
/*
* The story of _OSI(Linux)
*
* From pre-history through Linux-2.6.22,
* Linux responded TRUE upon a BIOS OSI(Linux) query.
*
* Unfortunately, reference BIOS writers got wind of this
* and put OSI(Linux) in their example code, quickly exposing
* this string as ill-conceived and opening the door to
* an un-bounded number of BIOS incompatibilities.
*
* For example, OSI(Linux) was used on resume to re-POST a
* video card on one system, because Linux at that time
* could not do a speedy restore in its native driver.
* But then upon gaining quick native restore capability,
* Linux has no way to tell the BIOS to skip the time-consuming
* POST -- putting Linux at a permanent performance disadvantage.
* On another system, the BIOS writer used OSI(Linux)
* to infer native OS support for IPMI! On other systems,
* OSI(Linux) simply got in the way of Linux claiming to
* be compatible with other operating systems, exposing
* BIOS issues such as skipped device initialization.
*
* So "Linux" turned out to be a really poor chose of
* OSI string, and from Linux-2.6.23 onward we respond FALSE.
*
* BIOS writers should NOT query _OSI(Linux) on future systems.
* Linux will complain on the console when it sees it, and return FALSE.
* To get Linux to return TRUE for your system will require
* a kernel source update to add a DMI entry,
* or boot with "acpi_osi=Linux"
*/
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};
static u32 acpi_osi_handler(acpi_string interface, u32 supported)
{
if (!strcmp("Linux", interface)) {
printk_once(KERN_NOTICE FW_BUG PREFIX
"BIOS _OSI(Linux) query %s%s\n",
osi_linux.enable ? "honored" : "ignored",
osi_linux.cmdline ? " via cmdline" :
osi_linux.dmi ? " via DMI" : "");
}
if (!strcmp("Darwin", interface)) {
/*
* Apple firmware will behave poorly if it receives positive
* answers to "Darwin" and any other OS. Respond positively
* to Darwin and then disable all other vendor strings.
*/
acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
supported = ACPI_UINT32_MAX;
}
return supported;
}
static void __init acpi_request_region (struct acpi_generic_address *gas,
unsigned int length, char *desc)
{
@ -582,7 +512,7 @@ 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)
acpi_string *new_val)
{
if (!init_val || !new_val)
return AE_BAD_PARAMETER;
@ -602,280 +532,6 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
return AE_OK;
}
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);
}
#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
#include <linux/earlycpio.h>
#include <linux/memblock.h>
static u64 acpi_tables_addr;
static int all_tables_size;
/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
{
u8 sum = 0;
u8 *end = buffer + length;
while (buffer < end)
sum = (u8) (sum + *(buffer++));
return sum;
}
/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
static const char * const table_sigs[] = {
ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
#define ACPI_OVERRIDE_TABLES 64
static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES);
#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
void __init acpi_initrd_override(void *data, size_t size)
{
int sig, no, table_nr = 0, total_offset = 0;
long offset = 0;
struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file;
if (data == NULL || size == 0)
return;
for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
file = find_cpio_data(cpio_path, data, size, &offset);
if (!file.data)
break;
data += offset;
size -= offset;
if (file.size < sizeof(struct acpi_table_header)) {
pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
cpio_path, file.name);
continue;
}
table = file.data;
for (sig = 0; table_sigs[sig]; sig++)
if (!memcmp(table->signature, table_sigs[sig], 4))
break;
if (!table_sigs[sig]) {
pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
cpio_path, file.name);
continue;
}
if (file.size != table->length) {
pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
cpio_path, file.name);
continue;
}
if (acpi_table_checksum(file.data, table->length)) {
pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
cpio_path, file.name);
continue;
}
pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
table->signature, cpio_path, file.name, table->length);
all_tables_size += table->length;
acpi_initrd_files[table_nr].data = file.data;
acpi_initrd_files[table_nr].size = file.size;
table_nr++;
}
if (table_nr == 0)
return;
acpi_tables_addr =
memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
all_tables_size, PAGE_SIZE);
if (!acpi_tables_addr) {
WARN_ON(1);
return;
}
/*
* Only calling e820_add_reserve does not work and the
* tables are invalid (memory got used) later.
* memblock_reserve works as expected and the tables won't get modified.
* But it's not enough on X86 because ioremap will
* complain later (used by acpi_os_map_memory) that the pages
* that should get mapped are not marked "reserved".
* Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
* works fine.
*/
memblock_reserve(acpi_tables_addr, all_tables_size);
arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
/*
* early_ioremap only can remap 256k one time. If we map all
* tables one time, we will hit the limit. Need to map chunks
* one by one during copying the same as that in relocate_initrd().
*/
for (no = 0; no < table_nr; no++) {
unsigned char *src_p = acpi_initrd_files[no].data;
phys_addr_t size = acpi_initrd_files[no].size;
phys_addr_t dest_addr = acpi_tables_addr + total_offset;
phys_addr_t slop, clen;
char *dest_p;
total_offset += size;
while (size) {
slop = dest_addr & ~PAGE_MASK;
clen = size;
if (clen > MAP_CHUNK_SIZE - slop)
clen = MAP_CHUNK_SIZE - slop;
dest_p = early_ioremap(dest_addr & PAGE_MASK,
clen + slop);
memcpy(dest_p + slop, src_p, clen);
early_iounmap(dest_p, clen + slop);
src_p += clen;
dest_addr += clen;
size -= clen;
}
}
}
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
acpi_physical_address *address, u32 *length)
{
int table_offset = 0;
int table_index = 0;
struct acpi_table_header *table;
u32 table_length;
*length = 0;
*address = 0;
if (!acpi_tables_addr)
return AE_OK;
while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
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_length = table->length;
/* Only override tables matched */
if (test_bit(table_index, acpi_initrd_installed) ||
memcmp(existing_table->signature, table->signature, 4) ||
memcmp(table->oem_table_id, existing_table->oem_table_id,
ACPI_OEM_TABLE_ID_SIZE)) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
*length = table_length;
*address = acpi_tables_addr + table_offset;
acpi_table_taint(existing_table);
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
set_bit(table_index, acpi_initrd_installed);
break;
next_table:
table_offset += table_length;
table_index++;
}
return AE_OK;
}
void __init acpi_initrd_initialize_tables(void)
{
int table_offset = 0;
int table_index = 0;
u32 table_length;
struct acpi_table_header *table;
if (!acpi_tables_addr)
return;
while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
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;
}
table_length = table->length;
/* Skip RSDT/XSDT which should only be used for override */
if (test_bit(table_index, acpi_initrd_installed) ||
ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
acpi_table_taint(table);
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
acpi_install_table(acpi_tables_addr + table_offset, TRUE);
set_bit(table_index, acpi_initrd_installed);
next_table:
table_offset += table_length;
table_index++;
}
}
#else
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
acpi_physical_address *address,
u32 *table_length)
{
*table_length = 0;
*address = 0;
return AE_OK;
}
void __init acpi_initrd_initialize_tables(void)
{
}
#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
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;
}
static irqreturn_t acpi_irq(int irq, void *dev_id)
{
u32 handled;
@ -1717,156 +1373,6 @@ static int __init acpi_os_name_setup(char *str)
__setup("acpi_os_name=", acpi_os_name_setup);
#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;
}
static void __init acpi_cmdline_osi_linux(unsigned int enable)
{
osi_linux.cmdline = 1; /* cmdline set the default and override DMI */
osi_linux.dmi = 0;
set_osi_linux(enable);
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;
}
/*
* Modify the list of "OS Interfaces" reported to BIOS via _OSI
*
* empty string disables _OSI
* string starting with '!' disables that string
* otherwise string is added to list, augmenting built-in strings
*/
static void __init acpi_osi_setup_late(void)
{
struct osi_setup_entry *osi;
char *str;
int i;
acpi_status status;
if (osi_linux.default_disabling) {
status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
if (ACPI_SUCCESS(status))
printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
}
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
str = osi->string;
if (*str == '\0')
break;
if (osi->enable) {
status = acpi_install_interface(str);
if (ACPI_SUCCESS(status))
printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
} else {
status = acpi_remove_interface(str);
if (ACPI_SUCCESS(status))
printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
}
}
}
static int __init osi_setup(char *str)
{
if (str && !strcmp("Linux", str))
acpi_cmdline_osi_linux(1);
else if (str && !strcmp("!Linux", str))
acpi_cmdline_osi_linux(0);
else
acpi_osi_setup(str);
return 1;
}
__setup("acpi_osi=", osi_setup);
/*
* Disable the auto-serialization of named objects creation methods.
*
@ -1986,12 +1492,6 @@ int acpi_resources_are_enforced(void)
}
EXPORT_SYMBOL(acpi_resources_are_enforced);
bool acpi_osi_is_win8(void)
{
return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
}
EXPORT_SYMBOL(acpi_osi_is_win8);
/*
* Deallocate the memory for a spinlock.
*/
@ -2157,8 +1657,7 @@ acpi_status __init acpi_os_initialize1(void)
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();
acpi_osi_init();
return AE_OK;
}

View File

@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/irq.h>
#include "internal.h"
@ -437,17 +438,15 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
* enabled system.
*/
#define ACPI_MAX_IRQS 256
#define ACPI_MAX_ISA_IRQ 16
#define ACPI_MAX_ISA_IRQS 16
#define PIRQ_PENALTY_PCI_AVAILABLE (0)
#define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
#define PIRQ_PENALTY_PCI_USING (16*16*16)
#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
@ -457,9 +456,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */
0, /* IRQ9 PCI, often acpi */
0, /* IRQ10 PCI */
0, /* IRQ11 PCI */
PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
@ -467,39 +466,58 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
/* >IRQ15 */
};
int __init acpi_irq_penalty_init(void)
static int acpi_irq_pci_sharing_penalty(int irq)
{
struct acpi_pci_link *link;
int penalty = 0;
list_for_each_entry(link, &acpi_link_list, list) {
/*
* If a link is active, penalize its IRQ heavily
* so we try to choose a different IRQ.
*/
if (link->irq.active && link->irq.active == irq)
penalty += PIRQ_PENALTY_PCI_USING;
else {
int i;
/*
* Update penalties to facilitate IRQ balancing.
* If a link is inactive, penalize the IRQs it
* might use, but not as severely.
*/
list_for_each_entry(link, &acpi_link_list, list) {
for (i = 0; i < link->irq.possible_count; i++)
if (link->irq.possible[i] == irq)
penalty += PIRQ_PENALTY_PCI_POSSIBLE /
link->irq.possible_count;
}
}
return penalty;
}
static int acpi_irq_get_penalty(int irq)
{
int penalty = 0;
if (irq < ACPI_MAX_ISA_IRQS)
penalty += acpi_isa_irq_penalty[irq];
/*
* reflect the possible and active irqs in the penalty table --
* useful for breaking ties.
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
* with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
* use for PCI IRQs.
*/
if (link->irq.possible_count) {
int penalty =
PIRQ_PENALTY_PCI_POSSIBLE /
link->irq.possible_count;
if (irq == acpi_gbl_FADT.sci_interrupt) {
u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
acpi_irq_penalty[link->irq.
possible[i]] +=
penalty;
if (type != IRQ_TYPE_LEVEL_LOW)
penalty += PIRQ_PENALTY_ISA_ALWAYS;
else
penalty += PIRQ_PENALTY_PCI_USING;
}
} else if (link->irq.active) {
acpi_irq_penalty[link->irq.active] +=
PIRQ_PENALTY_PCI_POSSIBLE;
}
}
return 0;
penalty += acpi_irq_pci_sharing_penalty(irq);
return penalty;
}
static int acpi_irq_balance = -1; /* 0: static, 1: balance */
@ -547,12 +565,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
* the use of IRQs 9, 10, 11, and >15.
*/
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
if (acpi_irq_penalty[irq] >
acpi_irq_penalty[link->irq.possible[i]])
if (acpi_irq_get_penalty(irq) >
acpi_irq_get_penalty(link->irq.possible[i]))
irq = link->irq.possible[i];
}
}
if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
"Try pci=noacpi or acpi=off\n",
acpi_device_name(link->device),
@ -568,7 +586,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
acpi_device_bid(link->device));
return -ENODEV;
} else {
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
acpi_device_name(link->device),
acpi_device_bid(link->device), link->irq.active);
@ -778,7 +795,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
}
/*
* modify acpi_irq_penalty[] from cmdline
* modify acpi_isa_irq_penalty[] from cmdline
*/
static int __init acpi_irq_penalty_update(char *str, int used)
{
@ -787,23 +804,24 @@ static int __init acpi_irq_penalty_update(char *str, int used)
for (i = 0; i < 16; i++) {
int retval;
int irq;
int new_penalty;
retval = get_option(&str, &irq);
if (!retval)
break; /* no number found */
if (irq < 0)
continue;
if (irq >= ARRAY_SIZE(acpi_irq_penalty))
/* see if this is a ISA IRQ */
if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS))
continue;
if (used)
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
new_penalty = acpi_irq_get_penalty(irq) +
PIRQ_PENALTY_ISA_USED;
else
acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
new_penalty = 0;
acpi_isa_irq_penalty[irq] = new_penalty;
if (retval != 2) /* no next number */
break;
}
@ -819,34 +837,15 @@ static int __init acpi_irq_penalty_update(char *str, int used)
*/
void acpi_penalize_isa_irq(int irq, int active)
{
if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
if (active)
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
else
acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
}
if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING;
}
bool acpi_isa_irq_available(int irq)
{
return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
}
/*
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
* PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
* PCI IRQs.
*/
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
{
if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
else
acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
}
return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) ||
acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
}
/*

View File

@ -26,6 +26,11 @@
#include "internal.h"
#include "sleep.h"
/*
* Some HW-full platforms do not have _S5, so they may need
* to leverage efi power off for a shutdown.
*/
bool acpi_no_s5;
static u8 sleep_states[ACPI_S_STATE_COUNT];
static void acpi_sleep_tts_switch(u32 acpi_state)
@ -882,6 +887,8 @@ int __init acpi_sleep_init(void)
sleep_states[ACPI_STATE_S5] = 1;
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
} else {
acpi_no_s5 = true;
}
supported[0] = 0;

View File

@ -555,23 +555,22 @@ static void acpi_global_event_handler(u32 event_type, acpi_handle device,
static int get_status(u32 index, acpi_event_status *status,
acpi_handle *handle)
{
int result = 0;
int result;
if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
goto end;
return -EINVAL;
if (index < num_gpes) {
result = acpi_get_gpe_device(index, handle);
if (result) {
ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
"Invalid GPE 0x%x", index));
goto end;
return result;
}
result = acpi_get_gpe_status(*handle, index, status);
} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
result = acpi_get_event_status(index - num_gpes, status);
end:
return result;
}

View File

@ -32,8 +32,14 @@
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/bootmem.h>
#include <linux/earlycpio.h>
#include <linux/memblock.h>
#include "internal.h"
#ifdef CONFIG_ACPI_CUSTOM_DSDT
#include CONFIG_ACPI_CUSTOM_DSDT_FILE
#endif
#define ACPI_MAX_TABLES 128
static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
@ -433,6 +439,314 @@ static void __init check_multiple_madt(void)
return;
}
static void acpi_table_taint(struct acpi_table_header *table)
{
pr_warn("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);
}
#ifdef CONFIG_ACPI_TABLE_UPGRADE
static u64 acpi_tables_addr;
static int all_tables_size;
/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
{
u8 sum = 0;
u8 *end = buffer + length;
while (buffer < end)
sum = (u8) (sum + *(buffer++));
return sum;
}
/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
static const char * const table_sigs[] = {
ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
#define NR_ACPI_INITRD_TABLES 64
static struct cpio_data __initdata acpi_initrd_files[NR_ACPI_INITRD_TABLES];
static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
static void __init acpi_table_initrd_init(void *data, size_t size)
{
int sig, no, table_nr = 0, total_offset = 0;
long offset = 0;
struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file;
if (data == NULL || size == 0)
return;
for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) {
file = find_cpio_data(cpio_path, data, size, &offset);
if (!file.data)
break;
data += offset;
size -= offset;
if (file.size < sizeof(struct acpi_table_header)) {
pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
cpio_path, file.name);
continue;
}
table = file.data;
for (sig = 0; table_sigs[sig]; sig++)
if (!memcmp(table->signature, table_sigs[sig], 4))
break;
if (!table_sigs[sig]) {
pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
cpio_path, file.name);
continue;
}
if (file.size != table->length) {
pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
cpio_path, file.name);
continue;
}
if (acpi_table_checksum(file.data, table->length)) {
pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
cpio_path, file.name);
continue;
}
pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
table->signature, cpio_path, file.name, table->length);
all_tables_size += table->length;
acpi_initrd_files[table_nr].data = file.data;
acpi_initrd_files[table_nr].size = file.size;
table_nr++;
}
if (table_nr == 0)
return;
acpi_tables_addr =
memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
all_tables_size, PAGE_SIZE);
if (!acpi_tables_addr) {
WARN_ON(1);
return;
}
/*
* Only calling e820_add_reserve does not work and the
* tables are invalid (memory got used) later.
* memblock_reserve works as expected and the tables won't get modified.
* But it's not enough on X86 because ioremap will
* complain later (used by acpi_os_map_memory) that the pages
* that should get mapped are not marked "reserved".
* Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
* works fine.
*/
memblock_reserve(acpi_tables_addr, all_tables_size);
arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
/*
* early_ioremap only can remap 256k one time. If we map all
* tables one time, we will hit the limit. Need to map chunks
* one by one during copying the same as that in relocate_initrd().
*/
for (no = 0; no < table_nr; no++) {
unsigned char *src_p = acpi_initrd_files[no].data;
phys_addr_t size = acpi_initrd_files[no].size;
phys_addr_t dest_addr = acpi_tables_addr + total_offset;
phys_addr_t slop, clen;
char *dest_p;
total_offset += size;
while (size) {
slop = dest_addr & ~PAGE_MASK;
clen = size;
if (clen > MAP_CHUNK_SIZE - slop)
clen = MAP_CHUNK_SIZE - slop;
dest_p = early_ioremap(dest_addr & PAGE_MASK,
clen + slop);
memcpy(dest_p + slop, src_p, clen);
early_iounmap(dest_p, clen + slop);
src_p += clen;
dest_addr += clen;
size -= clen;
}
}
}
static acpi_status
acpi_table_initrd_override(struct acpi_table_header *existing_table,
acpi_physical_address *address, u32 *length)
{
int table_offset = 0;
int table_index = 0;
struct acpi_table_header *table;
u32 table_length;
*length = 0;
*address = 0;
if (!acpi_tables_addr)
return AE_OK;
while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
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_length = table->length;
/* Only override tables matched */
if (memcmp(existing_table->signature, table->signature, 4) ||
memcmp(table->oem_id, existing_table->oem_id,
ACPI_OEM_ID_SIZE) ||
memcmp(table->oem_table_id, existing_table->oem_table_id,
ACPI_OEM_TABLE_ID_SIZE)) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
/*
* Mark the table to avoid being used in
* acpi_table_initrd_scan() and check the revision.
*/
if (test_and_set_bit(table_index, acpi_initrd_installed) ||
existing_table->oem_revision >= table->oem_revision) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
*length = table_length;
*address = acpi_tables_addr + table_offset;
pr_info("Table Upgrade: override [%4.4s-%6.6s-%8.8s]\n",
table->signature, table->oem_id,
table->oem_table_id);
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
break;
next_table:
table_offset += table_length;
table_index++;
}
return AE_OK;
}
static void __init acpi_table_initrd_scan(void)
{
int table_offset = 0;
int table_index = 0;
u32 table_length;
struct acpi_table_header *table;
if (!acpi_tables_addr)
return;
while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
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;
}
table_length = table->length;
/* Skip RSDT/XSDT which should only be used for override */
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
/*
* Mark the table to avoid being used in
* acpi_table_initrd_override(). Though this is not possible
* because override is disabled in acpi_install_table().
*/
if (test_and_set_bit(table_index, acpi_initrd_installed)) {
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
goto next_table;
}
pr_info("Table Upgrade: install [%4.4s-%6.6s-%8.8s]\n",
table->signature, table->oem_id,
table->oem_table_id);
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
acpi_install_table(acpi_tables_addr + table_offset, TRUE);
next_table:
table_offset += table_length;
table_index++;
}
}
#else
static void __init acpi_table_initrd_init(void *data, size_t size)
{
}
static acpi_status
acpi_table_initrd_override(struct acpi_table_header *existing_table,
acpi_physical_address *address,
u32 *table_length)
{
*table_length = 0;
*address = 0;
return AE_OK;
}
static void __init acpi_table_initrd_scan(void)
{
}
#endif /* CONFIG_ACPI_TABLE_UPGRADE */
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
acpi_physical_address *address,
u32 *table_length)
{
return acpi_table_initrd_override(existing_table, address,
table_length);
}
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;
}
void __init early_acpi_table_init(void *data, size_t size)
{
acpi_table_initrd_init(data, size);
}
/*
* acpi_table_init()
*
@ -457,7 +771,7 @@ int __init acpi_table_init(void)
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
if (ACPI_FAILURE(status))
return -EINVAL;
acpi_initrd_initialize_tables();
acpi_table_initrd_scan();
check_multiple_madt();
return 0;

View File

@ -707,7 +707,7 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
EXPORT_SYMBOL(acpi_check_dsm);
/**
* acpi_dev_present - Detect presence of a given ACPI device in the system.
* acpi_dev_found - Detect presence of a given ACPI device in the namespace.
* @hid: Hardware ID of the device.
*
* Return %true if the device was present at the moment of invocation.
@ -719,7 +719,7 @@ EXPORT_SYMBOL(acpi_check_dsm);
* instead). Calling from module_init() is fine (which is synonymous
* with device_initcall()).
*/
bool acpi_dev_present(const char *hid)
bool acpi_dev_found(const char *hid)
{
struct acpi_device_bus_id *acpi_device_bus_id;
bool found = false;
@ -734,7 +734,7 @@ bool acpi_dev_present(const char *hid)
return found;
}
EXPORT_SYMBOL(acpi_dev_present);
EXPORT_SYMBOL(acpi_dev_found);
/*
* acpi_backlight= handling, this is done here rather then in video_detect.c

View File

@ -358,7 +358,7 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void)
if (!(video_caps & ACPI_VIDEO_BACKLIGHT))
return acpi_backlight_vendor;
if (acpi_osi_is_win8() && backlight_device_registered(BACKLIGHT_RAW))
if (acpi_osi_is_win8() && backlight_device_get_by_type(BACKLIGHT_RAW))
return acpi_backlight_native;
return acpi_backlight_video;

View File

@ -793,15 +793,6 @@ static acpi_status __init AMW0_find_mailled(void)
return AE_OK;
}
static int AMW0_set_cap_acpi_check_device_found __initdata;
static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
u32 level, void *context, void **retval)
{
AMW0_set_cap_acpi_check_device_found = 1;
return AE_OK;
}
static const struct acpi_device_id norfkill_ids[] __initconst = {
{ "VPC2004", 0},
{ "IBM0068", 0},
@ -816,9 +807,10 @@ static int __init AMW0_set_cap_acpi_check_device(void)
const struct acpi_device_id *id;
for (id = norfkill_ids; id->id[0]; id++)
acpi_get_devices(id->id, AMW0_set_cap_acpi_check_device_cb,
NULL, NULL);
return AMW0_set_cap_acpi_check_device_found;
if (acpi_dev_found(id->id))
return true;
return false;
}
static acpi_status __init AMW0_set_capabilities(void)

View File

@ -204,30 +204,10 @@ static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
}
}
static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
void *context, void **retval)
{
pr_warn("Found legacy ATKD device (%s)\n", EEEPC_ACPI_HID);
*(bool *)context = true;
return AE_CTRL_TERMINATE;
}
static int eeepc_wmi_check_atkd(void)
{
acpi_status status;
bool found = false;
status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device,
&found, NULL);
if (ACPI_FAILURE(status) || !found)
return 0;
return -1;
}
static int eeepc_wmi_probe(struct platform_device *pdev)
{
if (eeepc_wmi_check_atkd()) {
if (acpi_dev_found(EEEPC_ACPI_HID)) {
pr_warn("Found legacy ATKD device (%s)\n", EEEPC_ACPI_HID);
pr_warn("WMI device present, but legacy ATKD device is also "
"present and enabled\n");
pr_warn("You probably booted with acpi_osi=\"Linux\" or "

View File

@ -338,31 +338,9 @@ config INTEL_QUARK_DTS_THERMAL
hot & critical. The critical trip point default value is set by
underlying BIOS/Firmware.
config INT340X_THERMAL
tristate "ACPI INT340X thermal drivers"
depends on X86 && ACPI
select THERMAL_GOV_USER_SPACE
select ACPI_THERMAL_REL
select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE
select THERMAL_WRITABLE_TRIPS
help
Newer laptops and tablets that use ACPI may have thermal sensors and
other devices with thermal control capabilities outside the core
CPU/SOC, for thermal safety reasons.
They are exposed for the OS to use via the INT3400 ACPI device object
as the master, and INT3401~INT340B ACPI device objects as the slaves.
Enable this to expose the temperature information and cooling ability
from these objects to userspace via the normal thermal framework.
This means that a wide range of applications and GUI widgets can show
the information to the user or use this information for making
decisions. For example, the Intel Thermal Daemon can use this
information to allow the user to select his laptop to run without
turning on the fans.
config ACPI_THERMAL_REL
tristate
depends on ACPI
menu "ACPI INT340X thermal drivers"
source drivers/thermal/int340x_thermal/Kconfig
endmenu
config INTEL_PCH_THERMAL
tristate "Intel PCH Thermal Reporting Driver"

View File

@ -0,0 +1,42 @@
#
# ACPI INT340x thermal drivers configuration
#
config INT340X_THERMAL
tristate "ACPI INT340X thermal drivers"
depends on X86 && ACPI
select THERMAL_GOV_USER_SPACE
select ACPI_THERMAL_REL
select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE
help
Newer laptops and tablets that use ACPI may have thermal sensors and
other devices with thermal control capabilities outside the core
CPU/SOC, for thermal safety reasons.
They are exposed for the OS to use via the INT3400 ACPI device object
as the master, and INT3401~INT340B ACPI device objects as the slaves.
Enable this to expose the temperature information and cooling ability
from these objects to userspace via the normal thermal framework.
This means that a wide range of applications and GUI widgets can show
the information to the user or use this information for making
decisions. For example, the Intel Thermal Daemon can use this
information to allow the user to select his laptop to run without
turning on the fans.
config ACPI_THERMAL_REL
tristate
depends on ACPI
if INT340X_THERMAL
config INT3406_THERMAL
tristate "ACPI INT3406 display thermal driver"
depends on ACPI_VIDEO
help
The display thermal device represents the LED/LCD display panel
that may or may not include touch support. The main function of
the display thermal device is to allow control of the display
brightness in order to address a thermal condition or to reduce
power consumed by display device.
endif

View File

@ -3,4 +3,5 @@ obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal_zone.o
obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o
obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o
obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o
obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o
obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o

View File

@ -0,0 +1,236 @@
/*
* INT3406 thermal driver for display participant device
*
* Copyright (C) 2016, Intel Corporation
* Authors: Aaron Lu <aaron.lu@intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/thermal.h>
#include <acpi/video.h>
#define INT3406_BRIGHTNESS_LIMITS_CHANGED 0x80
struct int3406_thermal_data {
int upper_limit;
int upper_limit_index;
int lower_limit;
int lower_limit_index;
acpi_handle handle;
struct acpi_video_device_brightness *br;
struct backlight_device *raw_bd;
struct thermal_cooling_device *cooling_dev;
};
static int int3406_thermal_to_raw(int level, struct int3406_thermal_data *d)
{
int max_level = d->br->levels[d->br->count - 1];
int raw_max = d->raw_bd->props.max_brightness;
return level * raw_max / max_level;
}
static int int3406_thermal_to_acpi(int level, struct int3406_thermal_data *d)
{
int raw_max = d->raw_bd->props.max_brightness;
int max_level = d->br->levels[d->br->count - 1];
return level * max_level / raw_max;
}
static int
int3406_thermal_get_max_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int index = d->lower_limit_index ? d->lower_limit_index : 2;
*state = d->br->count - 1 - index;
return 0;
}
static int
int3406_thermal_set_cur_state(struct thermal_cooling_device *cooling_dev,
unsigned long state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int level, raw_level;
if (state > d->br->count - 3)
return -EINVAL;
state = d->br->count - 1 - state;
level = d->br->levels[state];
if ((d->upper_limit && level > d->upper_limit) ||
(d->lower_limit && level < d->lower_limit))
return -EINVAL;
raw_level = int3406_thermal_to_raw(level, d);
return backlight_device_set_brightness(d->raw_bd, raw_level);
}
static int
int3406_thermal_get_cur_state(struct thermal_cooling_device *cooling_dev,
unsigned long *state)
{
struct int3406_thermal_data *d = cooling_dev->devdata;
int raw_level, level, i;
int *levels = d->br->levels;
raw_level = d->raw_bd->props.brightness;
level = int3406_thermal_to_acpi(raw_level, d);
/*
* There is no 1:1 mapping between the firmware interface level with the
* raw interface level, we will have to find one that is close enough.
*/
for (i = 2; i < d->br->count; i++) {
if (level < levels[i]) {
if (i == 2)
break;
if ((level - levels[i - 1]) < (levels[i] - level))
i--;
break;
}
}
*state = d->br->count - 1 - i;
return 0;
}
static const struct thermal_cooling_device_ops video_cooling_ops = {
.get_max_state = int3406_thermal_get_max_state,
.get_cur_state = int3406_thermal_get_cur_state,
.set_cur_state = int3406_thermal_set_cur_state,
};
static int int3406_thermal_get_index(int *array, int nr, int value)
{
int i;
for (i = 0; i < nr; i++) {
if (array[i] == value)
break;
}
return i == nr ? -ENOENT : i;
}
static void int3406_thermal_get_limit(struct int3406_thermal_data *d)
{
acpi_status status;
unsigned long long lower_limit, upper_limit;
int index;
status = acpi_evaluate_integer(d->handle, "DDDL", NULL, &lower_limit);
if (ACPI_SUCCESS(status)) {
index = int3406_thermal_get_index(d->br->levels, d->br->count,
lower_limit);
if (index > 0) {
d->lower_limit = (int)lower_limit;
d->lower_limit_index = index;
}
}
status = acpi_evaluate_integer(d->handle, "DDPC", NULL, &upper_limit);
if (ACPI_SUCCESS(status)) {
index = int3406_thermal_get_index(d->br->levels, d->br->count,
upper_limit);
if (index > 0) {
d->upper_limit = (int)upper_limit;
d->upper_limit_index = index;
}
}
}
static void int3406_notify(acpi_handle handle, u32 event, void *data)
{
if (event == INT3406_BRIGHTNESS_LIMITS_CHANGED)
int3406_thermal_get_limit(data);
}
static int int3406_thermal_probe(struct platform_device *pdev)
{
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct int3406_thermal_data *d;
struct backlight_device *bd;
int ret;
if (!ACPI_HANDLE(&pdev->dev))
return -ENODEV;
d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
d->handle = ACPI_HANDLE(&pdev->dev);
bd = backlight_device_get_by_type(BACKLIGHT_RAW);
if (!bd)
return -ENODEV;
d->raw_bd = bd;
ret = acpi_video_get_levels(ACPI_COMPANION(&pdev->dev), &d->br);
if (ret)
return ret;
int3406_thermal_get_limit(d);
d->cooling_dev = thermal_cooling_device_register(acpi_device_bid(adev),
d, &video_cooling_ops);
if (IS_ERR(d->cooling_dev))
goto err;
ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
int3406_notify, d);
if (ret)
goto err_cdev;
platform_set_drvdata(pdev, d);
return 0;
err_cdev:
thermal_cooling_device_unregister(d->cooling_dev);
err:
kfree(d->br);
return -ENODEV;
}
static int int3406_thermal_remove(struct platform_device *pdev)
{
struct int3406_thermal_data *d = platform_get_drvdata(pdev);
thermal_cooling_device_unregister(d->cooling_dev);
kfree(d->br);
return 0;
}
static const struct acpi_device_id int3406_thermal_match[] = {
{"INT3406", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, int3406_thermal_match);
static struct platform_driver int3406_thermal_driver = {
.probe = int3406_thermal_probe,
.remove = int3406_thermal_remove,
.driver = {
.name = "int3406 thermal",
.owner = THIS_MODULE,
.acpi_match_table = int3406_thermal_match,
},
};
module_platform_driver(int3406_thermal_driver);
MODULE_DESCRIPTION("INT3406 Thermal driver");
MODULE_LICENSE("GPL v2");

View File

@ -164,6 +164,30 @@ static ssize_t brightness_show(struct device *dev,
return sprintf(buf, "%d\n", bd->props.brightness);
}
int backlight_device_set_brightness(struct backlight_device *bd,
unsigned long brightness)
{
int rc = -ENXIO;
mutex_lock(&bd->ops_lock);
if (bd->ops) {
if (brightness > bd->props.max_brightness)
rc = -EINVAL;
else {
pr_debug("set brightness to %lu\n", brightness);
bd->props.brightness = brightness;
backlight_update_status(bd);
rc = 0;
}
}
mutex_unlock(&bd->ops_lock);
backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);
return rc;
}
EXPORT_SYMBOL(backlight_device_set_brightness);
static ssize_t brightness_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@ -175,24 +199,9 @@ static ssize_t brightness_store(struct device *dev,
if (rc)
return rc;
rc = -ENXIO;
rc = backlight_device_set_brightness(bd, brightness);
mutex_lock(&bd->ops_lock);
if (bd->ops) {
if (brightness > bd->props.max_brightness)
rc = -EINVAL;
else {
pr_debug("set brightness to %lu\n", brightness);
bd->props.brightness = brightness;
backlight_update_status(bd);
rc = count;
}
}
mutex_unlock(&bd->ops_lock);
backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);
return rc;
return rc ? rc : count;
}
static DEVICE_ATTR_RW(brightness);
@ -380,7 +389,7 @@ struct backlight_device *backlight_device_register(const char *name,
}
EXPORT_SYMBOL(backlight_device_register);
bool backlight_device_registered(enum backlight_type type)
struct backlight_device *backlight_device_get_by_type(enum backlight_type type)
{
bool found = false;
struct backlight_device *bd;
@ -394,9 +403,9 @@ bool backlight_device_registered(enum backlight_type type)
}
mutex_unlock(&backlight_dev_list_mutex);
return found;
return found ? bd : NULL;
}
EXPORT_SYMBOL(backlight_device_registered);
EXPORT_SYMBOL(backlight_device_get_by_type);
/**
* backlight_device_unregister - unregisters a backlight device object.

View File

@ -87,7 +87,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
.package.elements = (eles) \
}
bool acpi_dev_present(const char *hid);
bool acpi_dev_found(const char *hid);
#ifdef CONFIG_ACPI

View File

@ -78,7 +78,6 @@
/* ACPI PCI Interrupt Link (pci_link.c) */
int acpi_irq_penalty_init(void);
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name);
int acpi_pci_link_free_irq(acpi_handle handle);

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