4 * Copyright (c) 2006 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>
26 struct acpi_table_header
28 char signature
[4]; /* ACPI signature (4 ASCII characters) */
29 uint32_t length
; /* Length of table, in bytes, including header */
30 uint8_t revision
; /* ACPI Specification minor version # */
31 uint8_t checksum
; /* To make sum of entire table == 0 */
32 char oem_id
[6]; /* OEM identification */
33 char oem_table_id
[8]; /* OEM table identification */
34 uint32_t oem_revision
; /* OEM revision number */
35 char asl_compiler_id
[4]; /* ASL compiler vendor ID */
36 uint32_t asl_compiler_revision
; /* ASL compiler revision number */
37 } __attribute__((packed
));
40 size_t acpi_tables_len
;
42 static int acpi_checksum(const uint8_t *data
, int len
)
46 for(i
= 0; i
< len
; i
++)
51 int acpi_table_add(const char *t
)
53 static const char *dfl_id
= "QEMUQEMU";
54 char buf
[1024], *p
, *f
;
55 struct acpi_table_header acpi_hdr
;
58 struct acpi_table_header
*acpi_hdr_p
;
61 memset(&acpi_hdr
, 0, sizeof(acpi_hdr
));
63 if (get_param_value(buf
, sizeof(buf
), "sig", t
)) {
64 strncpy(acpi_hdr
.signature
, buf
, 4);
66 strncpy(acpi_hdr
.signature
, dfl_id
, 4);
68 if (get_param_value(buf
, sizeof(buf
), "rev", t
)) {
69 val
= strtoul(buf
, &p
, 10);
70 if (val
> 255 || *p
!= '\0')
75 acpi_hdr
.revision
= (int8_t)val
;
77 if (get_param_value(buf
, sizeof(buf
), "oem_id", t
)) {
78 strncpy(acpi_hdr
.oem_id
, buf
, 6);
80 strncpy(acpi_hdr
.oem_id
, dfl_id
, 6);
83 if (get_param_value(buf
, sizeof(buf
), "oem_table_id", t
)) {
84 strncpy(acpi_hdr
.oem_table_id
, buf
, 8);
86 strncpy(acpi_hdr
.oem_table_id
, dfl_id
, 8);
89 if (get_param_value(buf
, sizeof(buf
), "oem_rev", t
)) {
90 val
= strtol(buf
, &p
, 10);
96 acpi_hdr
.oem_revision
= cpu_to_le32(val
);
98 if (get_param_value(buf
, sizeof(buf
), "asl_compiler_id", t
)) {
99 strncpy(acpi_hdr
.asl_compiler_id
, buf
, 4);
101 strncpy(acpi_hdr
.asl_compiler_id
, dfl_id
, 4);
104 if (get_param_value(buf
, sizeof(buf
), "asl_compiler_rev", t
)) {
105 val
= strtol(buf
, &p
, 10);
111 acpi_hdr
.asl_compiler_revision
= cpu_to_le32(val
);
113 if (!get_param_value(buf
, sizeof(buf
), "data", t
)) {
117 length
= sizeof(acpi_hdr
);
122 char *n
= strchr(f
, ':');
125 if(stat(f
, &s
) < 0) {
126 fprintf(stderr
, "Can't stat file '%s': %s\n", f
, strerror(errno
));
137 acpi_tables_len
= sizeof(uint16_t);
138 acpi_tables
= qemu_mallocz(acpi_tables_len
);
140 acpi_tables
= qemu_realloc(acpi_tables
,
141 acpi_tables_len
+ sizeof(uint16_t) + length
);
142 p
= acpi_tables
+ acpi_tables_len
;
143 acpi_tables_len
+= sizeof(uint16_t) + length
;
145 *(uint16_t*)p
= cpu_to_le32(length
);
146 p
+= sizeof(uint16_t);
147 memcpy(p
, &acpi_hdr
, sizeof(acpi_hdr
));
148 off
= sizeof(acpi_hdr
);
154 char *n
= strchr(f
, ':');
157 fd
= open(f
, O_RDONLY
);
161 if(fstat(fd
, &s
) < 0) {
166 /* off < length is necessary because file size can be changed
168 while(s
.st_size
&& off
< length
) {
170 r
= read(fd
, p
+ off
, s
.st_size
);
174 } else if ((r
< 0 && errno
!= EINTR
) || r
== 0) {
186 /* don't pass random value in process to guest */
187 memset(p
+ off
, 0, length
- off
);
190 acpi_hdr_p
= (struct acpi_table_header
*)p
;
191 acpi_hdr_p
->length
= cpu_to_le32(length
);
192 acpi_hdr_p
->checksum
= acpi_checksum((uint8_t*)p
, length
);
193 /* increase number of tables */
194 (*(uint16_t*)acpi_tables
) =
195 cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables
) + 1);
199 qemu_free(acpi_tables
);
206 uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT
*pm1
, int64_t overflow_time
)
208 int64_t d
= acpi_pm_tmr_get_clock();
209 if (d
>= overflow_time
) {
210 pm1
->sts
|= ACPI_BITMASK_TIMER_STATUS
;
215 void acpi_pm1_evt_write_sts(ACPIPM1EVT
*pm1
, ACPIPMTimer
*tmr
, uint16_t val
)
217 uint16_t pm1_sts
= acpi_pm1_evt_get_sts(pm1
, tmr
->overflow_time
);
218 if (pm1_sts
& val
& ACPI_BITMASK_TIMER_STATUS
) {
219 /* if TMRSTS is reset, then compute the new overflow time */
220 acpi_pm_tmr_calc_overflow_time(tmr
);
225 void acpi_pm1_evt_power_down(ACPIPM1EVT
*pm1
, ACPIPMTimer
*tmr
)
228 qemu_system_shutdown_request();
229 } else if (pm1
->en
& ACPI_BITMASK_POWER_BUTTON_ENABLE
) {
230 pm1
->sts
|= ACPI_BITMASK_POWER_BUTTON_STATUS
;
231 tmr
->update_sci(tmr
);
235 void acpi_pm1_evt_reset(ACPIPM1EVT
*pm1
)
242 void acpi_pm_tmr_update(ACPIPMTimer
*tmr
, bool enable
)
246 /* schedule a timer interruption if needed */
248 expire_time
= muldiv64(tmr
->overflow_time
, get_ticks_per_sec(),
250 qemu_mod_timer(tmr
->timer
, expire_time
);
252 qemu_del_timer(tmr
->timer
);
256 void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer
*tmr
)
258 int64_t d
= acpi_pm_tmr_get_clock();
259 tmr
->overflow_time
= (d
+ 0x800000LL
) & ~0x7fffffLL
;
262 uint32_t acpi_pm_tmr_get(ACPIPMTimer
*tmr
)
264 uint32_t d
= acpi_pm_tmr_get_clock();;
268 static void acpi_pm_tmr_timer(void *opaque
)
270 ACPIPMTimer
*tmr
= opaque
;
271 tmr
->update_sci(tmr
);
274 void acpi_pm_tmr_init(ACPIPMTimer
*tmr
, acpi_update_sci_fn update_sci
)
276 tmr
->update_sci
= update_sci
;
277 tmr
->timer
= qemu_new_timer_ns(vm_clock
, acpi_pm_tmr_timer
, tmr
);
280 void acpi_pm_tmr_reset(ACPIPMTimer
*tmr
)
282 tmr
->overflow_time
= 0;
283 qemu_del_timer(tmr
->timer
);
287 void acpi_pm1_cnt_init(ACPIPM1CNT
*pm1_cnt
, qemu_irq cmos_s3
)
289 pm1_cnt
->cmos_s3
= cmos_s3
;
292 void acpi_pm1_cnt_write(ACPIPM1EVT
*pm1a
, ACPIPM1CNT
*pm1_cnt
, uint16_t val
)
294 pm1_cnt
->cnt
= val
& ~(ACPI_BITMASK_SLEEP_ENABLE
);
296 if (val
& ACPI_BITMASK_SLEEP_ENABLE
) {
297 /* change suspend type */
298 uint16_t sus_typ
= (val
>> 10) & 7;
300 case 0: /* soft power off */
301 qemu_system_shutdown_request();
304 /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
305 Pretend that resume was caused by power button */
307 (ACPI_BITMASK_WAKE_STATUS
| ACPI_BITMASK_POWER_BUTTON_STATUS
);
308 qemu_system_reset_request();
309 qemu_irq_raise(pm1_cnt
->cmos_s3
);
316 void acpi_pm1_cnt_update(ACPIPM1CNT
*pm1_cnt
,
317 bool sci_enable
, bool sci_disable
)
319 /* ACPI specs 3.0, 4.7.2.5 */
321 pm1_cnt
->cnt
|= ACPI_BITMASK_SCI_ENABLE
;
322 } else if (sci_disable
) {
323 pm1_cnt
->cnt
&= ~ACPI_BITMASK_SCI_ENABLE
;
327 void acpi_pm1_cnt_reset(ACPIPM1CNT
*pm1_cnt
)
330 if (pm1_cnt
->cmos_s3
) {
331 qemu_irq_lower(pm1_cnt
->cmos_s3
);
336 void acpi_gpe_init(ACPIGPE
*gpe
, uint8_t len
)
339 gpe
->sts
= qemu_mallocz(len
/ 2);
340 gpe
->en
= qemu_mallocz(len
/ 2);
343 void acpi_gpe_blk(ACPIGPE
*gpe
, uint32_t blk
)
348 void acpi_gpe_reset(ACPIGPE
*gpe
)
350 memset(gpe
->sts
, 0, gpe
->len
/ 2);
351 memset(gpe
->en
, 0, gpe
->len
/ 2);
354 static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE
*gpe
, uint32_t addr
)
358 if (addr
< gpe
->len
/ 2) {
359 cur
= gpe
->sts
+ addr
;
360 } else if (addr
< gpe
->len
) {
361 cur
= gpe
->en
+ addr
- gpe
->len
/ 2;
369 void acpi_gpe_ioport_writeb(ACPIGPE
*gpe
, uint32_t addr
, uint32_t val
)
374 cur
= acpi_gpe_ioport_get_ptr(gpe
, addr
);
375 if (addr
< gpe
->len
/ 2) {
377 *cur
= (*cur
) & ~val
;
378 } else if (addr
< gpe
->len
) {
386 uint32_t acpi_gpe_ioport_readb(ACPIGPE
*gpe
, uint32_t addr
)
392 cur
= acpi_gpe_ioport_get_ptr(gpe
, addr
);