]> xenbits.xen.org Git - xenclient/ioemu-pq.git/commitdiff
Merge oem-features, sleep button and thermal management support to 3.4 branch.
authorKamala Narasimhan <kamala.narasimhan@citrix.com>
Mon, 13 Apr 2009 03:27:00 +0000 (23:27 -0400)
committerKamala Narasimhan <kamala.narasimhan@citrix.com>
Mon, 13 Apr 2009 03:27:00 +0000 (23:27 -0400)
xen-3.4/oem-features [new file with mode: 0644]
xen-3.4/series
xen-3.4/sleep-btn-support [new file with mode: 0644]
xen-3.4/thermal-management [new file with mode: 0644]

diff --git a/xen-3.4/oem-features b/xen-3.4/oem-features
new file mode 100644 (file)
index 0000000..cb8ae2b
--- /dev/null
@@ -0,0 +1,950 @@
+diff --git a/hw/acpi-wmi.h b/hw/acpi-wmi.h
+new file mode 100644
+index 0000000..af99c1c
+--- /dev/null
++++ b/hw/acpi-wmi.h
+@@ -0,0 +1,99 @@
++/******************************************************************************
++ * acpi-wmi.h
++ *
++ * Interface to /proc/misc/xen-acpi-wmi
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * 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; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++/*  NOTE:  This header is a duplicate of drivers/xen/acpi-wmi/acpi-wmi.h in our
++ *  kernel repo.  As we don't share headers between kernel and userspace, we have
++ *  the same header in two places.  It is important to keep the two headers in sync
++ *  to avoid incompatibilities.
++ */ 
++
++#ifndef _XEN_WMI_ACPI
++#define _XEN_WMI_ACPI
++
++/*
++ * Userspace Interface
++ */
++
++#define XEN_WMI_DEVICE_NAME              "xen-acpi-wmi"
++#define XEN_WMI_GUID_SIZE                16
++
++#define XEN_WMI_SUCCESS                  0
++#define XEN_WMI_UNSUPPORTED_TYPE        -1
++#define XEN_WMI_BUFFER_TOO_SMALL        -11
++#define XEN_WMI_NOT_ENOUGH_MEMORY       -12
++#define XEN_WMI_EFAULT                  -14
++#define XEN_WMI_INVALID_ARGUMENT        -22
++#define XEN_WMI_ENOIOCTLCMD             -515
++ 
++#define XEN_WMI_IOCTL_CALL_METHOD        100
++#define XEN_WMI_IOCTL_QUERY_OBJECT       101
++#define XEN_WMI_IOCTL_SET_OBJECT         102
++#define XEN_WMI_IOCTL_GET_EVENT_DATA     103
++
++typedef unsigned char byte;
++
++typedef struct xen_wmi_buffer {
++    size_t       length; 
++    void        *pointer;
++    size_t      *copied_length;
++} xen_wmi_buffer_t;
++
++typedef struct xen_wmi_obj_invocation_data { 
++    byte                       guid[XEN_WMI_GUID_SIZE];
++    union {
++        struct {
++            ushort             instance;
++            uint               method_id;
++            xen_wmi_buffer_t   in_buf;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_method_arg;
++
++        struct {
++            ushort             instance;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_query_obj_arg;
++
++        struct {
++            ushort             instance;
++            xen_wmi_buffer_t   in_buf;
++        } xen_wmi_set_obj_arg;
++
++        struct {
++            ushort             event_id;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_event_data_arg;
++    } xen_wmi_arg;
++} xen_wmi_obj_invocation_data_t;
++
++#endif /* _XEN_WMI_ACPI */
++
+diff --git a/hw/pc.h b/hw/pc.h
+index e1ce52d..dbd691a 100644
+--- a/hw/pc.h
++++ b/hw/pc.h
+@@ -109,6 +109,8 @@ void acpi_ac_adapter_state_changed(void);
+ void acpi_power_button_pressed(void);
+ void acpi_lid_state_changed(void);
++void acpi_oem_event(void);
++
+ /* hpet.c */
+ extern int no_hpet;
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index d25f004..277f106 100644
+--- a/hw/piix4acpi.c
++++ b/hw/piix4acpi.c
+@@ -29,6 +29,7 @@
+ #include "sysemu.h"
+ #include "qemu-xen.h"
+ #include "battery_mgmt.h"
++#include "xen_acpi_wmi.h"
+ #include <xen/hvm/ioreq.h>
+ #include <xen/hvm/params.h>
+@@ -57,6 +58,7 @@
+ #define ACPI_AC_POWER_STATE_BIT 0x1c
+ #define ACPI_POWER_BUTTON_BIT 0x1
+ #define ACPI_LID_STATE_BIT 0x17 
++#define ACPI_OEM_EVENT_BIT 0x18
+ typedef struct AcpiDeviceState AcpiDeviceState;
+ AcpiDeviceState *acpi_device_table;
+@@ -194,6 +196,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
+     register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d);
+     battery_mgmt_init(pci_dev);
++    xen_acpi_wmi_init(pci_dev);
+ }
+ static inline int test_bit(uint8_t *map, int bit)
+@@ -248,6 +251,19 @@ void acpi_lid_state_changed(void)
+     }
+ }
++void acpi_oem_event(void)
++{
++    GPEState *s = &gpe_state;
++
++    if ( !test_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT) &&
++          test_bit(&s->gpe0_en[0], ACPI_OEM_EVENT_BIT) ) {
++        set_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT);
++        s->sci_asserted = 1;
++        fprintf(logfile, "Raising oem event irq\n");
++        qemu_irq_raise(sci_irq);
++    }
++}
++
+ #ifdef CONFIG_PASSTHROUGH
+ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
+diff --git a/hw/xen_acpi_wmi.c b/hw/xen_acpi_wmi.c
+new file mode 100644
+index 0000000..5d378d0
+--- /dev/null
++++ b/hw/xen_acpi_wmi.c
+@@ -0,0 +1,654 @@
++/*
++ * xen_acpi_wmi.c
++ *
++ * Copyright (c) 2009  Kamala Narasimhan
++ * Copyright (c) 2009  Citrix Systems, Inc.
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/* Xen ACPI WMI implementation - 
++ * OEMs expose their value add functionalites through firmware level WMI 
++ * acpi objects.  To support the underlying OEM value add within guest 
++ * space, we expose a WMI psuedo device object at our vACPI layer.  That 
++ * vACPI layer relies on the below implementation to communication to the
++ * base firmware (through xen wmi module and linux acpi wmi wrapper 
++ * driver) either it be to execute a WMI method or query or set 
++ * data or recieve wmi event data. 
++ */
++
++/* NOTE:  As the vACPI layer is written to send request and take response in a 
++ * synchronized way, there isn't a need to add synchronization logic here.
++ */
++
++#include "hw.h"
++#include "pc.h"
++#include "qemu-xen.h"
++#include "isa.h" 
++#include "xen_acpi_wmi.h"
++
++#ifndef CONFIG_NO_XEN_ACPI_WMI
++
++#define XEN_WMI_DEFAULT_OUTPUT_BUFFER_SIZE 256
++
++static xen_acpi_wmi_cmd_info_t cmd_info;
++static int xen_wmi_device = -ENODEV;  
++extern FILE *logfile;
++extern int domid;
++
++/* #define XEN_ACPI_WMI_DEBUG */
++/* #define XEN_ACPI_WMI_DEBUG_EXT */
++
++/*
++ * xen_acpi_wmi_set_guid
++ */
++void xen_acpi_wmi_set_guid(uint8_t val)
++{
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED )
++    {
++        fprintf(logfile, 
++            "XEN WMI: Unable to set guid with invalid invocation type!\n");
++        return;
++    }
++
++    if ( cmd_info.current_index >= XEN_WMI_GUID_SIZE )
++    {
++        fprintf(logfile, "XEN WMI: Guid array index out of range - %d!!!\n", 
++                cmd_info.current_index);
++        cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;  
++        return;
++    }
++
++    cmd_info.invocation_data.guid[cmd_info.current_index] = val;
++    cmd_info.current_index++;
++}
++
++/*
++ * xen_acpi_wmi_set_cmd_instance
++ */
++void xen_acpi_wmi_set_cmd_instance(uint32_t val)
++{
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED ) 
++    {
++        fprintf(logfile, 
++            "XEN WMI: Unable to set cmd instance with invalid invocation type!\n");
++        return;
++    }
++
++    switch( cmd_info.invocation_type )
++    {
++        case XEN_ACPI_WMI_EXEC_METHOD:
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.instance = val;
++            break;
++        case XEN_ACPI_WMI_QUERY_OBJECT:
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.instance = val;
++            break;
++        case XEN_ACPI_WMI_SET_OBJECT:
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.instance = val;
++            break;
++        default:
++            fprintf(logfile, 
++                "Invalid attempt to set instance for current invocation type!\n");
++            break;
++    }
++}
++
++/*
++ * xen_acpi_wmi_set_method_id
++ */
++void xen_acpi_wmi_set_method_id(uint32_t val)
++{
++    if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD )
++    {
++        fprintf(logfile,
++            "Unable to set method id for the current invocation type!\n");
++        return;
++    }
++
++    cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.method_id = val;
++}
++
++/*
++ * xen_acpi_wmi_get_input_buffer
++ */
++xen_wmi_buffer_t *xen_acpi_wmi_get_input_buffer(void)
++{
++    if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD  &&
++         cmd_info.invocation_type != XEN_ACPI_WMI_SET_OBJECT )
++        return 0;
++
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
++        return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.in_buf;
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_SET_OBJECT )
++        return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.in_buf;
++
++    return 0;
++}
++
++/*
++ * xen_acpi_wmi_set_buffer_size
++ * Guest vACPI layer passes to us the size of the input buffer it is 
++ * about to transfer to ioemu  and this method stores the passed in size  
++ * apart from allocating a buffer with the provided size. 
++ */
++void xen_acpi_wmi_set_in_buffer_size(uint32_t val)
++{
++    xen_wmi_buffer_t *buffer;
++
++    buffer = xen_acpi_wmi_get_input_buffer();
++    if ( buffer == NULL )
++        return;
++
++    cmd_info.current_index = 0;
++    buffer->length = val;
++    buffer->pointer = malloc(val); 
++}
++
++/*
++ * xen_acpi_wmi_set_in_buffer
++ */
++void xen_acpi_wmi_set_in_buffer(uint8_t val)
++{
++    xen_wmi_buffer_t *buffer;
++
++    buffer = xen_acpi_wmi_get_input_buffer();
++    if ( buffer == NULL )
++        return;
++
++    if ( cmd_info.current_index >= buffer->length )
++    {
++        fprintf(logfile, 
++            "XEN WMI: Cannot write beyond allocated input buffer size!!!\n");
++        return;
++    }
++
++    ((byte *)buffer->pointer)[cmd_info.current_index] = val;
++    cmd_info.current_index++;
++}
++
++/*
++ * xen_wmi_get_output_buffer
++ */
++xen_wmi_buffer_t *xen_acpi_wmi_get_output_buffer(void)
++{
++    if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD &&
++         cmd_info.invocation_type != XEN_ACPI_WMI_QUERY_OBJECT &&
++         cmd_info.invocation_type != XEN_ACPI_WMI_GET_EVENT_DATA )
++    {
++        fprintf(logfile,
++            "XEN WMI: Output buffer not available for current invocation type!\n"); 
++        return 0;
++    }
++
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
++        return  &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.out_buf;
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_QUERY_OBJECT )
++        return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.out_buf;
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_GET_EVENT_DATA )
++        return  &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.out_buf;
++
++    return 0;
++}
++
++/*
++ * xen_acpi_wmi_allocate_output_buffer
++ */
++void xen_acpi_wmi_allocate_output_buffer(size_t length)
++{
++    xen_wmi_buffer_t *buffer;
++
++    buffer = xen_acpi_wmi_get_output_buffer();
++    if ( buffer == NULL )
++        return;
++
++    buffer->length = (length > 0) ? length : XEN_WMI_DEFAULT_OUTPUT_BUFFER_SIZE;
++    buffer->pointer = malloc(buffer->length); 
++    memset(buffer->pointer, 0, buffer->length);
++
++    buffer->copied_length = malloc(sizeof(size_t));
++    memset(buffer->copied_length, 0, sizeof(size_t));
++}
++
++/*
++ * xen_acpi_wmi_reallocate_output_buffer
++ */
++int xen_acpi_wmi_reallocate_output_buffer()
++{
++    xen_wmi_buffer_t *buffer;
++
++    buffer = xen_acpi_wmi_get_output_buffer();
++    if ( buffer == NULL || buffer->copied_length == NULL || buffer->pointer == NULL )
++        return XEN_WMI_NOT_ENOUGH_MEMORY; 
++
++    /* If required length is less than allocated length,
++     * we shouldn't have failed; no point in rellocating.
++     * @TODO: Rename copied_length to something more appropriate.
++     */
++    if ( *buffer->copied_length <= buffer->length )
++        return XEN_WMI_NOT_ENOUGH_MEMORY;
++
++    free(buffer->pointer);
++    buffer->pointer = malloc(*buffer->copied_length);
++    memset(buffer->pointer, 0, *buffer->copied_length);
++    buffer->length = *buffer->copied_length;
++    return XEN_WMI_SUCCESS;
++}
++
++/*
++ * xen_acpi_wmi_free_input_buffer 
++ */
++void xen_acpi_wmi_free_input_buffer(void)
++{
++    xen_wmi_buffer_t *buffer;
++
++    buffer = xen_acpi_wmi_get_input_buffer();
++    if ( buffer == NULL )
++        return;
++
++    if ( buffer->length > 0 )
++        free(buffer->pointer);
++    buffer->length = 0;
++}
++
++#ifdef XEN_ACPI_WMI_DEBUG
++
++/*
++ * xen_acpi_wmi_print_input_buffer
++ */
++void xen_acpi_wmi_print_input_buffer(xen_wmi_buffer_t *in_buf)
++{
++    int count;
++
++    fprintf(logfile, "In buffer length - %d\n", in_buf->length);
++    fprintf(logfile, "In buffer:  ");
++    for( count = 0; count < in_buf->length; count++ )
++        fprintf(logfile, " %d,  ", ((byte *)in_buf->pointer)[count]);
++    fprintf(logfile, "\n");
++}
++
++/*
++ * xen_acpi_wmi_print_input_info
++ */
++void xen_acpi_wmi_print_input_info(void)
++{
++    int count;
++
++    fprintf(logfile, "Command invocation type - %d\n", cmd_info.invocation_type);
++    fprintf(logfile, "Invocation Data:  \n");
++    fprintf(logfile, "Guid: ");
++
++    for (count=0; count < XEN_WMI_GUID_SIZE; count++)
++        fprintf(logfile,"%d  ", cmd_info.invocation_data.guid[count]);
++
++    fprintf(logfile, "\n");
++
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
++    {
++        fprintf(logfile, 
++            "Instance id - %d\n", 
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.instance);
++        fprintf(logfile,
++            "Method id - %d\n", 
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.method_id);
++        xen_acpi_wmi_print_input_buffer(
++            &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.in_buf);
++    }
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_QUERY_OBJECT )
++    {
++        fprintf(logfile,
++            "Instance id - %d\n", 
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.instance);
++    }
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_SET_OBJECT )
++    {
++        fprintf(logfile,
++            "Instance id - %d\n", 
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.instance);
++        xen_acpi_wmi_print_input_buffer(
++            &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.in_buf);
++    }
++    else if ( cmd_info.invocation_type == XEN_ACPI_WMI_GET_EVENT_DATA )
++    {
++        fprintf(logfile,
++            "Event id - %d\n",
++            cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.event_id);
++    } 
++}
++
++/*
++ * xen_acpi_wmi_print_output_buffer
++ */
++void xen_acpi_wmi_print_output_buffer(void)
++{
++    int count;
++    xen_wmi_buffer_t *buffer = xen_acpi_wmi_get_output_buffer();
++
++    if ( buffer == NULL || buffer->copied_length == NULL || *buffer->copied_length == 0 )
++        return;
++
++    fprintf(logfile, "XEN WMI: Output buffer size is - %d\n",
++            *buffer->copied_length);
++    fprintf(logfile, "XEN WMI output buffer is - ");
++    for (count=0; count < *buffer->copied_length; count++)
++        fprintf(logfile," %d, ", ((byte *)buffer->pointer)[count]);
++
++    fprintf(logfile, "\n");
++}
++
++#endif /* XEN_ACPI_WMI_DEBUG */
++
++/*
++ * xen_acpi_wmi_execute
++ */
++void xen_acpi_wmi_execute(void)
++{
++    int request, ret;
++
++    if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED )
++    {
++        fprintf(logfile,
++            "Unable to execute command for the given invocation type!\n");
++        return;
++    }
++
++    switch ( cmd_info.invocation_type )
++    {
++        case XEN_ACPI_WMI_EXEC_METHOD:
++            request = XEN_WMI_IOCTL_CALL_METHOD;
++            break;
++        case XEN_ACPI_WMI_QUERY_OBJECT:
++            request = XEN_WMI_IOCTL_QUERY_OBJECT; 
++            break;
++        case XEN_ACPI_WMI_SET_OBJECT:
++            request = XEN_WMI_IOCTL_SET_OBJECT;
++            break;
++        case XEN_ACPI_WMI_GET_EVENT_DATA:
++            request = XEN_WMI_IOCTL_GET_EVENT_DATA;
++            break;
++        default:
++            fprintf(logfile,
++                "Unable to execute command for the given invocation type!\n");
++            return;
++    } 
++
++    xen_acpi_wmi_allocate_output_buffer(0);
++#ifdef XEN_ACPI_WMI_DEBUG
++    fprintf(logfile, "XEN WMI Invoking ioctl - %d\n", cmd_info.invocation_type);
++    xen_acpi_wmi_print_input_info();
++#endif
++    ret = ioctl(xen_wmi_device, request, &cmd_info.invocation_data);
++    if ( ret == XEN_WMI_BUFFER_TOO_SMALL )
++    {
++        if ( xen_acpi_wmi_reallocate_output_buffer() == XEN_WMI_SUCCESS )
++            ret = ioctl(xen_wmi_device, request, &cmd_info.invocation_data);
++    }
++
++    if ( ret != XEN_WMI_SUCCESS )
++        fprintf(logfile, "Xen WMI ioctl failed with error - %d\n", ret);
++
++#ifdef XEN_ACPI_WMI_DEBUG
++    xen_acpi_wmi_print_output_buffer();
++#endif
++
++    xen_acpi_wmi_free_input_buffer();
++}
++
++/*
++ * xen_acpi_wmi_set_event_id
++ */
++void xen_acpi_wmi_set_event_id(uint8_t event_id)
++{
++    if ( cmd_info.invocation_type != XEN_ACPI_WMI_GET_EVENT_DATA )
++    {
++        fprintf(logfile, 
++            "XEN WMI: Request to set event ID with incorrect invocation type!!!\n");        
++        return;
++    }
++
++    cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.event_id = event_id;
++}
++
++/*
++ * xen_acpi_wmi_cmd_port_read
++ */
++static uint32_t xen_acpi_wmi_cmd_port_read(void *opaque, uint32_t addr)
++{
++#ifdef XEN_ACPI_WMI_DEBUG_EXT
++    fprintf(logfile, "XEN WMI: In cmd port read - %d\n",
++        cmd_info.cmd_type);
++#endif
++    return cmd_info.cmd_type;
++}   
++
++/*
++ * xen_acpi_wmi_cmd_port_write
++ */
++static void xen_acpi_wmi_cmd_port_write(void *opaque, uint32_t addr, uint32_t val)
++{
++#ifdef XEN_ACPI_WMI_DEBUG_EXT
++    fprintf(logfile, "XEN WMI: In cmd port write - %d\n", val);
++#endif
++    cmd_info.cmd_type = val;
++    if ( val < XEN_ACPI_WMI_CMD_INIT || val >= XEN_ACPI_WMI_CMD_UNDEFINED )
++    {
++        fprintf(logfile,"XEN WMI: Unknown xen acpi wmi command - %d\n", val);
++        cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;
++        cmd_info.current_index = 0;
++        return; 
++    } 
++
++    if ( val == XEN_ACPI_WMI_CMD_EXECUTE )
++        xen_acpi_wmi_execute();
++}
++
++/*
++ * xen_acpi_wmi_data_port_readb
++ */
++static uint32_t xen_acpi_wmi_data_port_readb(void *opaque, uint32_t addr)
++{
++    xen_wmi_buffer_t *buffer;
++    byte ret;
++
++    if ( cmd_info.cmd_type == XEN_ACPI_WMI_CMD_OUT_BUFFER )
++    {
++        buffer = xen_acpi_wmi_get_output_buffer();
++        if ( buffer == NULL || buffer->copied_length == NULL )
++            return 0x0;
++
++        if ( *buffer->copied_length == 0 )
++            return 0x0;
++
++        if ( cmd_info.current_index >= *buffer->copied_length )
++        {
++            fprintf(logfile, 
++                "XEN WMI: Output buffer index overflow. Current - %d Max - %d\n",
++                 cmd_info.current_index, *buffer->copied_length);
++            cmd_info.cmd_type = XEN_ACPI_WMI_CMD_UNDEFINED; 
++            return 0x0;
++        }
++
++        ret = ((byte*)buffer->pointer)[cmd_info.current_index];
++        if ( cmd_info.current_index == buffer->length-1 )
++        {
++            /* @TODO: We expect that the firmware would read all of
++             * the output buffer before releasing it.  This
++             * could result in a leak if the firmware chooses
++             * to ignore the return buffer. It might make sense to
++             * introduce a cleanup command. */ 
++            cmd_info.cmd_type = XEN_ACPI_WMI_CMD_UNDEFINED; 
++            buffer->length = 0;
++            free(buffer->pointer);
++            buffer->pointer = NULL;
++            free(buffer->copied_length);
++            buffer->copied_length = NULL;
++        }
++
++#ifdef XEN_ACPI_WMI_DEBUG_EXT 
++        fprintf(logfile, "XEN WMI: Data port read returned - %d\n", ret);
++#endif
++        cmd_info.current_index++;
++        return ret;
++    } 
++
++    fprintf(logfile, "XEN WMI: Data port read byte.  Shouldn't be here!!!\n");
++    return 0x0;
++}  
++
++/*
++ * xen_acpi_wmi_data_port_writeb
++ */
++static void xen_acpi_wmi_data_port_writeb(void *opaque, uint32_t addr, uint32_t val)
++{
++#ifdef XEN_ACPI_WMI_DEBUG_EXT
++    fprintf(logfile, "XEN WMI: In data port write byte - %d\n", val);
++#endif
++
++    switch( cmd_info.cmd_type )
++    {
++        case XEN_ACPI_WMI_CMD_INIT:
++            cmd_info.invocation_type = val;
++            cmd_info.current_index = 0;
++            memset(&cmd_info.invocation_data, 0, sizeof(cmd_info.invocation_data));
++            break;
++        case XEN_ACPI_WMI_CMD_GUID:
++            xen_acpi_wmi_set_guid(val);
++            break;
++        case XEN_ACPI_WMI_CMD_IN_BUFFER:
++            xen_acpi_wmi_set_in_buffer(val);
++            break;
++        case XEN_ACPI_WMI_CMD_EVENT_ID:
++            xen_acpi_wmi_set_event_id(val);
++            break;
++        default:
++            fprintf(logfile, 
++                "XEN WMI: Attempting to write to data(byte) port with incompatible cmd type %d\n",    
++                    cmd_info.cmd_type);
++             break;
++    }    
++}
++
++/*
++ * xen_acpi_wmi_data_port_readl
++ */
++static uint32_t xen_acpi_wmi_data_port_readl(void *opaque, uint32_t addr)
++{
++    xen_wmi_buffer_t *buffer;
++
++    if ( cmd_info.cmd_type == XEN_ACPI_WMI_CMD_OUT_BUFFER_SIZE )
++    {
++        buffer = xen_acpi_wmi_get_output_buffer();
++        if ( buffer == NULL || buffer->copied_length == NULL )
++            return 0x0;
++
++        if (*buffer->copied_length == 0 )
++            return 0x0;
++
++        cmd_info.current_index = 0;
++#ifdef XEN_ACPI_WMI_DEBUG_EXT
++       fprintf(logfile, "XEN WMI: Output buffer length is - %d\n", *buffer->copied_length);
++#endif
++        return *buffer->copied_length;
++    }
++
++    fprintf(logfile, "XEN WMI: Data port read long.  Shouldn't be here!!!\n");
++    return 0x0;
++} 
++
++/*
++ * xen_acpi_wmi_data_port_writel
++ */
++static void xen_acpi_wmi_data_port_writel(void *opaque, uint32_t addr, uint32_t val)
++{
++#ifdef XEN_ACPI_WMI_DEBUG_EXT
++    fprintf(logfile, "XEN WMI: In data port write long - %d\n", val);
++#endif
++
++    switch( cmd_info.cmd_type )
++    {
++        case XEN_ACPI_WMI_CMD_OBJ_INSTANCE:
++            xen_acpi_wmi_set_cmd_instance(val);
++            break;
++        case XEN_ACPI_WMI_CMD_METHOD_ID:
++            xen_acpi_wmi_set_method_id(val);
++            break;
++        case XEN_ACPI_WMI_CMD_IN_BUFFER_SIZE:
++            xen_acpi_wmi_set_in_buffer_size(val);
++            break;
++        default:
++            fprintf(logfile,
++                "XEN WMI: Attempting to write to data(long) port with incompatible cmd type %d\n",
++                    cmd_info.cmd_type);
++             break;
++    }
++}
++
++/*
++ * xen_acpi_wmi_init
++ */
++void xen_acpi_wmi_init(PCIDevice *device)
++{
++    char dev_name[64];
++    char *oem_buffer;
++
++    cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;
++    cmd_info.current_index = 0;
++
++    oem_buffer = xenstore_device_model_read(domid, "oem_features", NULL);
++    if ( oem_buffer == NULL )
++    {
++#ifdef XEN_ACPI_WMI_DEBUG 
++        fprintf(logfile,"OEM value add disabled!\n");
++#endif
++        return;
++    }
++
++    sprintf(dev_name, "/dev/%s", XEN_WMI_DEVICE_NAME);
++    xen_wmi_device = open(dev_name, 0);
++    if ( xen_wmi_device < 0 )
++    {
++        fprintf(logfile, 
++            "XEN WMI: Unable to open device - %s\n", XEN_WMI_DEVICE_NAME);
++        return;
++    }
++
++    register_ioport_read(XEN_ACPI_WMI_CMD_PORT, 1, 1, xen_acpi_wmi_cmd_port_read, device);   
++    register_ioport_write(XEN_ACPI_WMI_CMD_PORT, 1, 1, xen_acpi_wmi_cmd_port_write, device); 
++    register_ioport_read(XEN_ACPI_WMI_DATA_PORTB, 1, 1, xen_acpi_wmi_data_port_readb, device);
++    register_ioport_write(XEN_ACPI_WMI_DATA_PORTB, 1, 1, xen_acpi_wmi_data_port_writeb, device);
++    register_ioport_read(XEN_ACPI_WMI_DATA_PORTL, 4, 4, xen_acpi_wmi_data_port_readl, device);
++    register_ioport_write(XEN_ACPI_WMI_DATA_PORTL, 4, 4, xen_acpi_wmi_data_port_writel, device);
++
++    xenstore_register_for_oem_events();
++#ifdef XEN_ACPI_WMI_DEBUG
++    fprintf(logfile, "XEN WMI:  XEN ACPI WMI registration succeeded!!!\n");
++#endif
++}
++
++/*
++ * xen_acpi_wmi_cleanup(void)
++ */
++void xen_acpi_wmi_cleanup(void)
++{
++    if ( xen_wmi_device > 0 )
++        close(xen_wmi_device);
++}
++
++#else
++
++void xen_acpi_wmi_init(PCIDevice *device) { }
++void xen_acpi_wmi_cleanup(void) { }
++
++#endif /* CONFIG_NO_XEN_ACPI_WMI */
++ 
+diff --git a/hw/xen_acpi_wmi.h b/hw/xen_acpi_wmi.h
+new file mode 100644
+index 0000000..91e4c00
+--- /dev/null
++++ b/hw/xen_acpi_wmi.h
+@@ -0,0 +1,66 @@
++/*
++ * xen_acpi_wmi.h
++ *
++ * Copyright (c) 2009  Kamala Narasimhan
++ * Copyright (c) 2009  Citrix Systems, Inc.
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _XEN_ACPI_WMI_H
++#define _XEN_ACPI_WMI_H
++
++#ifdef CONFIG_STUBDOM
++#define CONFIG_NO_XEN_ACPI_WMI
++#endif
++
++#include "acpi-wmi.h"
++
++#define XEN_ACPI_WMI_CMD_PORT   0x96
++#define XEN_ACPI_WMI_DATA_PORTB 0x98
++#define XEN_ACPI_WMI_DATA_PORTL 0x9A
++
++/* Values written to WMI command port */
++enum XEN_ACPI_WMI_COMMAND { XEN_ACPI_WMI_CMD_INIT = 100,
++                            XEN_ACPI_WMI_CMD_GUID,
++                            XEN_ACPI_WMI_CMD_OBJ_INSTANCE,
++                            XEN_ACPI_WMI_CMD_METHOD_ID,
++                            XEN_ACPI_WMI_CMD_IN_BUFFER,
++                            XEN_ACPI_WMI_CMD_IN_BUFFER_SIZE, 
++                            XEN_ACPI_WMI_CMD_EXECUTE,
++                            XEN_ACPI_WMI_CMD_OUT_BUFFER,
++                            XEN_ACPI_WMI_CMD_OUT_BUFFER_SIZE, 
++                            XEN_ACPI_WMI_CMD_EVENT_ID,
++                            XEN_ACPI_WMI_CMD_UNDEFINED }; 
++
++enum XEN_ACPI_WMI_OBJ_INVOCATION_TYPE { XEN_ACPI_WMI_EXEC_METHOD = 1,
++                                        XEN_ACPI_WMI_QUERY_OBJECT,
++                                        XEN_ACPI_WMI_SET_OBJECT,
++                                        XEN_ACPI_WMI_GET_EVENT_DATA,
++                                        XEN_ACPI_WMI_UNDEFINED };
++
++typedef struct xen_acpi_wmi_cmd_info {
++    enum XEN_ACPI_WMI_COMMAND cmd_type;
++    enum XEN_ACPI_WMI_OBJ_INVOCATION_TYPE invocation_type;
++    xen_wmi_obj_invocation_data_t invocation_data;
++    uint32_t current_index;
++} xen_acpi_wmi_cmd_info_t; 
++
++void xen_acpi_wmi_init(PCIDevice *device);
++void xen_acpi_wmi_cleanup(void);
++
++#endif /* _XEN_ACPI_WMI_H */
++
++
+diff --git a/qemu-xen.h b/qemu-xen.h
+index 61c0f25..81a2e33 100644
+--- a/qemu-xen.h
++++ b/qemu-xen.h
+@@ -118,6 +118,7 @@ int xenstore_refresh_battery_status(void);
+ void xenstore_register_for_pm_events(void);
+ int xenstore_read_ac_adapter_state(void);
+ int xenstore_read_lid_state(void);
++void xenstore_register_for_oem_events(void);
+ int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
+                                          uint32_t build_nr);
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index d52e99d..cdf7b59 100644
+--- a/xen-hooks.mak
++++ b/xen-hooks.mak
+@@ -35,6 +35,7 @@ OBJS += exec-dm.o
+ OBJS += pci_emulation.o
+ OBJS += helper2.o
+ OBJS += battery_mgmt.o
++OBJS += xen_acpi_wmi.o
+ OBJS += dom0_driver.o
+ OBJS += hid-linux.o
+ OBJS += intel.o
+diff --git a/xenstore.c b/xenstore.c
+index 3fa6115..5c33301 100644
+--- a/xenstore.c
++++ b/xenstore.c
+@@ -978,6 +978,11 @@ void xenstore_process_event(void *opaque)
+         goto out;
+     }
++    if (!strcmp(vec[XS_WATCH_TOKEN], "oemevt")) {
++        acpi_oem_event();
++        goto out;
++    }
++
+     if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
+         xenstore_process_logdirty_event();
+         goto out;
+@@ -1714,6 +1719,11 @@ void xenstore_register_for_pm_events(void)
+    xs_watch(xsh, "/pm/events/powerbuttonpressed", "pwrbuttonpressedevt");
+ }
++void xenstore_register_for_oem_events(void)
++{
++   xs_watch(xsh, "/oem/event", "oemevt");
++}
++
+ int xenstore_read_ac_adapter_state(void)
+ {
+     int ac_state = 1;
index d4add3b4a6dbe785b6e166d96ae75b7b244b8478..cd4c22ee523e18e1257f467bebf1da6ce9d71ee8 100644 (file)
@@ -7,3 +7,6 @@ intel
 battery_management
 use-vga-cmdline
 disable-aio
+oem-features
+sleep-btn-support
+thermal-management
diff --git a/xen-3.4/sleep-btn-support b/xen-3.4/sleep-btn-support
new file mode 100644 (file)
index 0000000..c3a5e6e
--- /dev/null
@@ -0,0 +1,66 @@
+diff --git a/hw/pc.h b/hw/pc.h
+index dbd691a..e43d490 100644
+--- a/hw/pc.h
++++ b/hw/pc.h
+@@ -107,6 +107,7 @@ void acpi_php_add(int);
+ void acpi_php_del(int);
+ void acpi_ac_adapter_state_changed(void);
+ void acpi_power_button_pressed(void);
++void acpi_sleep_button_pressed(void);
+ void acpi_lid_state_changed(void);
+ void acpi_oem_event(void);
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index 277f106..3e7a7d6 100644
+--- a/hw/piix4acpi.c
++++ b/hw/piix4acpi.c
+@@ -57,6 +57,7 @@
+ #define ACPI_PHP_SLOT_NUM NR_PCI_DEV
+ #define ACPI_AC_POWER_STATE_BIT 0x1c
+ #define ACPI_POWER_BUTTON_BIT 0x1
++#define ACPI_SLEEP_BUTTON_BIT 0x0
+ #define ACPI_LID_STATE_BIT 0x17 
+ #define ACPI_OEM_EVENT_BIT 0x18
+@@ -239,6 +240,18 @@ void acpi_power_button_pressed(void)
+     }  
+ }
++void acpi_sleep_button_pressed(void)
++{
++    GPEState *s = &gpe_state;
++
++    if ( !test_bit(&s->gpe0_sts[0], ACPI_SLEEP_BUTTON_BIT) &&
++          test_bit(&s->gpe0_en[0], ACPI_SLEEP_BUTTON_BIT) ) {
++        set_bit(&s->gpe0_sts[0], ACPI_SLEEP_BUTTON_BIT);
++        s->sci_asserted = 1;
++        qemu_irq_raise(sci_irq);
++    }
++}
++
+ void acpi_lid_state_changed(void)
+ {
+     GPEState *s = &gpe_state;
+diff --git a/xenstore.c b/xenstore.c
+index 5c33301..9e5d904 100644
+--- a/xenstore.c
++++ b/xenstore.c
+@@ -973,6 +973,10 @@ void xenstore_process_event(void *opaque)
+         goto out;
+     }
++    if (!strcmp(vec[XS_WATCH_TOKEN], "slpbuttonpressedevt")) {
++        acpi_sleep_button_pressed();
++    }
++
+     if (!strcmp(vec[XS_WATCH_TOKEN], "lidstatechangeevt")) {
+         acpi_lid_state_changed();
+         goto out;
+@@ -1717,6 +1721,7 @@ void xenstore_register_for_pm_events(void)
+    xs_watch(xsh, "/pm/events/acadapterstatechanged", "acadapterstatechangeevt");
+    xs_watch(xsh, "/pm/events/lidstatechanged", "lidstatechangeevt");
+    xs_watch(xsh, "/pm/events/powerbuttonpressed", "pwrbuttonpressedevt");
++   xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt");
+ }
+ void xenstore_register_for_oem_events(void)
diff --git a/xen-3.4/thermal-management b/xen-3.4/thermal-management
new file mode 100644 (file)
index 0000000..b8367e6
--- /dev/null
@@ -0,0 +1,244 @@
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index 3e7a7d6..5383032 100644
+--- a/hw/piix4acpi.c
++++ b/hw/piix4acpi.c
+@@ -198,6 +198,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
+     battery_mgmt_init(pci_dev);
+     xen_acpi_wmi_init(pci_dev);
++    thermal_mgmt_init(pci_dev);
+ }
+ static inline int test_bit(uint8_t *map, int bit)
+diff --git a/hw/thermal_mgmt.c b/hw/thermal_mgmt.c
+new file mode 100644
+index 0000000..649b622
+--- /dev/null
++++ b/hw/thermal_mgmt.c
+@@ -0,0 +1,79 @@
++/*
++ * thermal_mgmt.c
++ *
++ * Copyright (c) 2009  Kamala Narasimhan
++ * Copyright (c) 2009  Citrix Systems, Inc.
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/* Implementation Notes:  Following provides a minimal thermal zone implementation for
++ * HVM guest.  The vACPI layer exposes a single thermal zone with critical and current
++ * temperature objects which when invoked relies on the below to return back the critical
++ * and current temperature provided by the underlying firmware.
++ */
++
++#include "hw.h"
++#include "pc.h"
++#include "qemu-xen.h"
++#include "isa.h" 
++#include "thermal_mgmt.h"
++
++#ifndef CONFIG_NO_THERMAL_MGMT
++
++/* #define THERMAL_MGMT_DBG */
++
++extern FILE *logfile;
++
++static uint32_t thermal_port_1_readw(void *opaque, uint32_t addr)
++{
++    int current_temp;
++
++    xenstore_refresh_thermal_info();
++    current_temp = xenstore_read_current_temperature();
++#ifdef THERMAL_MGMT_DBG
++    fprintf(logfile, "Current temperature - %d\n", current_temp);
++#endif
++    return current_temp;
++}
++
++static uint32_t thermal_port_2_readw(void *opaque, uint32_t addr)
++{
++    int critical_temp;
++
++    xenstore_refresh_thermal_info();
++    critical_temp = xenstore_read_critical_temperature();
++#ifdef THERMAL_MGMT_DBG
++    fprintf(logfile, "Critical trip point temperature - %d\n", critical_temp);
++#endif
++    return critical_temp;
++}
++
++void thermal_mgmt_init(PCIDevice *device)
++{
++#ifdef THERMAL_MGMT_DBG
++    fprintf(logfile, "In thermal management init\n");
++#endif
++
++    register_ioport_read(THERMAL_PORT_1, 1, 2, thermal_port_1_readw, device);
++    register_ioport_read(THERMAL_PORT_2, 1, 2, thermal_port_2_readw, device);
++}
++
++#else
++
++void thermal_mgmt_init(PCIDevice *device) { }
++
++#endif
++
+diff --git a/hw/thermal_mgmt.h b/hw/thermal_mgmt.h
+new file mode 100644
+index 0000000..d83273b
+--- /dev/null
++++ b/hw/thermal_mgmt.h
+@@ -0,0 +1,35 @@
++/*
++ * thermal_mgmt.h
++ *
++ * Copyright (c) 2009  Kamala Narasimhan
++ * Copyright (c) 2009  Citrix Systems, Inc.
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _THERMAL_MGMT_H
++#define _THERMAL_MGMT_H
++
++#ifdef CONFIG_STUBDOM
++#define CONFIG_NO_THERMAL_MGMT
++#endif
++
++#define THERMAL_PORT_1 0x90
++#define THERMAL_PORT_2 0x92
++
++void thermal_mgmt_init(PCIDevice *device);
++
++#endif
++
+diff --git a/qemu-xen.h b/qemu-xen.h
+index 81a2e33..1410d4f 100644
+--- a/qemu-xen.h
++++ b/qemu-xen.h
+@@ -115,9 +115,12 @@ char *xenstore_vm_read(int domid, const char *key, unsigned int *len);
+ char *xenstore_device_model_read(int domid, const char *key, unsigned int *len);
+ char *xenstore_read_battery_data(int battery_status);
+ int xenstore_refresh_battery_status(void);
++int xenstore_refresh_thermal_info(void);
+ void xenstore_register_for_pm_events(void);
+ int xenstore_read_ac_adapter_state(void);
+ int xenstore_read_lid_state(void);
++int xenstore_read_current_temperature(void);
++int xenstore_read_critical_temperature(void);
+ void xenstore_register_for_oem_events(void);
+ int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
+                                          uint32_t build_nr);
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index cdf7b59..55dd477 100644
+--- a/xen-hooks.mak
++++ b/xen-hooks.mak
+@@ -36,6 +36,7 @@ OBJS += pci_emulation.o
+ OBJS += helper2.o
+ OBJS += battery_mgmt.o
+ OBJS += xen_acpi_wmi.o
++OBJS += thermal_mgmt.o
+ OBJS += dom0_driver.o
+ OBJS += hid-linux.o
+ OBJS += intel.o
+diff --git a/xenstore.c b/xenstore.c
+index 9e5d904..690b78e 100644
+--- a/xenstore.c
++++ b/xenstore.c
+@@ -1379,6 +1379,20 @@ static char *xenstore_extended_power_mgmt_read(const char *key, unsigned int *le
+     return value;
+ }
++int xenstore_extended_power_mgmt_read_int(char *key, int default_value)
++{
++    int value = default_value;
++    char *buffer;
++
++    buffer = xenstore_extended_power_mgmt_read(key, NULL);
++    if ( buffer == NULL )
++        return value;
++
++    value = strtoull(buffer, NULL, 10);
++    free(buffer);
++    return value;
++}
++
+ static int xenstore_extended_power_mgmt_write(const char *key, const char *value)
+ {
+     int ret;
+@@ -1431,6 +1445,11 @@ int xenstore_refresh_battery_status(void)
+     return xenstore_extended_power_mgmt_event_trigger("refreshbatterystatus", "1");
+ }
++int xenstore_refresh_thermal_info(void)
++{
++    return xenstore_extended_power_mgmt_event_trigger("refreshthermalinfo", "1");
++}
++
+ /*
+  * Create a store entry for a device (e.g., monitor, serial/parallel lines).
+  * The entry is <domain-path><storeString>/tty and the value is the name
+@@ -1731,28 +1750,21 @@ void xenstore_register_for_oem_events(void)
+ int xenstore_read_ac_adapter_state(void)
+ {
+-    int ac_state = 1;
+-    char *buffer;
+-
+-    buffer = xenstore_extended_power_mgmt_read("ac_adapter", NULL);
+-    if ( buffer == NULL )
+-        return ac_state;
+-
+-    ac_state = strtoull(buffer, NULL, 10);
+-    free(buffer);
+-    return ac_state;
++    return xenstore_extended_power_mgmt_read_int("ac_adapter", 1);
+ }
+ int xenstore_read_lid_state(void)
+ {
+-    int lid_state = 1;
+-    char * buffer;
++    return xenstore_extended_power_mgmt_read_int("lid_state", 1);
++}
+-    buffer = xenstore_extended_power_mgmt_read("lid_state", NULL);
+-    if ( buffer == NULL )
+-        return lid_state;
++int xenstore_read_current_temperature(void)
++{
++    return xenstore_extended_power_mgmt_read_int("current_temperature", 0);
++}
+-    lid_state = strtoull(buffer, NULL, 10);
+-    free(buffer);
+-    return lid_state;
++int xenstore_read_critical_temperature(void)
++{
++    return xenstore_extended_power_mgmt_read_int("critical_temperature", 100);
+ }
++