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/>
23 struct acpi_table_header
{
24 uint16_t _length
; /* our length, not actual part of the hdr */
25 /* XXX why we have 2 length fields here? */
26 char sig
[4]; /* ACPI signature (4 ASCII characters) */
27 uint32_t length
; /* Length of table, in bytes, including header */
28 uint8_t revision
; /* ACPI Specification minor version # */
29 uint8_t checksum
; /* To make sum of entire table == 0 */
30 char oem_id
[6]; /* OEM identification */
31 char oem_table_id
[8]; /* OEM table identification */
32 uint32_t oem_revision
; /* OEM revision number */
33 char asl_compiler_id
[4]; /* ASL compiler vendor ID */
34 uint32_t asl_compiler_revision
; /* ASL compiler revision number */
35 } __attribute__((packed
));
37 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
38 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */
40 static const char dfl_hdr
[ACPI_TABLE_HDR_SIZE
] =
41 "\0\0" /* fake _length (2) */
42 "QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */
43 "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
44 "QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */
48 size_t acpi_tables_len
;
50 static int acpi_checksum(const uint8_t *data
, int len
)
54 for (i
= 0; i
< len
; i
++) {
60 /* like strncpy() but zero-fills the tail of destination */
61 static void strzcpy(char *dst
, const char *src
, size_t size
)
63 size_t len
= strlen(src
);
67 memset(dst
+ len
, 0, size
- len
);
69 memcpy(dst
, src
, len
);
72 /* XXX fixme: this function uses obsolete argument parsing interface */
73 int acpi_table_add(const char *t
)
75 char buf
[1024], *p
, *f
;
77 size_t len
, start
, allen
;
81 struct acpi_table_header hdr
;
84 r
|= get_param_value(buf
, sizeof(buf
), "data", t
) ? 1 : 0;
85 r
|= get_param_value(buf
, sizeof(buf
), "file", t
) ? 2 : 0;
89 /* fallthrough for default behavior */
97 fprintf(stderr
, "acpitable: both data and file are specified\n");
102 allen
= sizeof(uint16_t);
103 acpi_tables
= qemu_mallocz(allen
);
105 allen
= acpi_tables_len
;
109 acpi_tables
= qemu_realloc(acpi_tables
, start
+ ACPI_TABLE_HDR_SIZE
);
110 allen
+= has_header
? ACPI_TABLE_PFX_SIZE
: ACPI_TABLE_HDR_SIZE
;
112 /* now read in the data files, reallocating buffer as needed */
114 for (f
= strtok(buf
, ":"); f
; f
= strtok(NULL
, ":")) {
115 int fd
= open(f
, O_RDONLY
);
118 fprintf(stderr
, "can't open file %s: %s\n", f
, strerror(errno
));
124 r
= read(fd
, data
, sizeof(data
));
128 acpi_tables
= qemu_realloc(acpi_tables
, allen
+ r
);
129 memcpy(acpi_tables
+ allen
, data
, r
);
131 } else if (errno
!= EINTR
) {
132 fprintf(stderr
, "can't read file %s: %s\n",
142 /* now fill in the header fields */
144 f
= acpi_tables
+ start
; /* start of the table */
147 /* copy the header to temp place to align the fields */
148 memcpy(&hdr
, has_header
? f
: dfl_hdr
, ACPI_TABLE_HDR_SIZE
);
150 /* length of the table minus our prefix */
151 len
= allen
- start
- ACPI_TABLE_PFX_SIZE
;
153 hdr
._length
= cpu_to_le16(len
);
155 if (get_param_value(buf
, sizeof(buf
), "sig", t
)) {
156 strzcpy(hdr
.sig
, buf
, sizeof(hdr
.sig
));
160 /* length of the table including header, in bytes */
162 /* check if actual length is correct */
163 val
= le32_to_cpu(hdr
.length
);
166 "warning: acpitable has wrong length,"
167 " header says %lu, actual size %zu bytes\n",
172 /* we may avoid putting length here if has_header is true */
173 hdr
.length
= cpu_to_le32(len
);
175 if (get_param_value(buf
, sizeof(buf
), "rev", t
)) {
176 val
= strtoul(buf
, &p
, 0);
177 if (val
> 255 || *p
) {
178 fprintf(stderr
, "acpitable: \"rev=%s\" is invalid\n", buf
);
181 hdr
.revision
= (uint8_t)val
;
185 if (get_param_value(buf
, sizeof(buf
), "oem_id", t
)) {
186 strzcpy(hdr
.oem_id
, buf
, sizeof(hdr
.oem_id
));
190 if (get_param_value(buf
, sizeof(buf
), "oem_table_id", t
)) {
191 strzcpy(hdr
.oem_table_id
, buf
, sizeof(hdr
.oem_table_id
));
195 if (get_param_value(buf
, sizeof(buf
), "oem_rev", t
)) {
196 val
= strtol(buf
, &p
, 0);
198 fprintf(stderr
, "acpitable: \"oem_rev=%s\" is invalid\n", buf
);
201 hdr
.oem_revision
= cpu_to_le32(val
);
205 if (get_param_value(buf
, sizeof(buf
), "asl_compiler_id", t
)) {
206 strzcpy(hdr
.asl_compiler_id
, buf
, sizeof(hdr
.asl_compiler_id
));
210 if (get_param_value(buf
, sizeof(buf
), "asl_compiler_rev", t
)) {
211 val
= strtol(buf
, &p
, 0);
213 fprintf(stderr
, "acpitable: \"%s=%s\" is invalid\n",
214 "asl_compiler_rev", buf
);
217 hdr
.asl_compiler_revision
= cpu_to_le32(val
);
221 if (!has_header
&& !changed
) {
222 fprintf(stderr
, "warning: acpitable: no table headers are specified\n");
226 /* now calculate checksum of the table, complete with the header */
227 /* we may as well leave checksum intact if has_header is true */
228 /* alternatively there may be a way to set cksum to a given value */
229 hdr
.checksum
= 0; /* for checksum calculation */
231 /* put header back */
232 memcpy(f
, &hdr
, sizeof(hdr
));
234 if (changed
|| !has_header
|| 1) {
235 ((struct acpi_table_header
*)f
)->checksum
=
236 acpi_checksum((uint8_t *)f
+ ACPI_TABLE_PFX_SIZE
, len
);
239 /* increase number of tables */
240 (*(uint16_t *)acpi_tables
) =
241 cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables
) + 1);
243 acpi_tables_len
= allen
;
249 uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT
*pm1
, int64_t overflow_time
)
251 int64_t d
= acpi_pm_tmr_get_clock();
252 if (d
>= overflow_time
) {
253 pm1
->sts
|= ACPI_BITMASK_TIMER_STATUS
;
258 void acpi_pm1_evt_write_sts(ACPIPM1EVT
*pm1
, ACPIPMTimer
*tmr
, uint16_t val
)
260 uint16_t pm1_sts
= acpi_pm1_evt_get_sts(pm1
, tmr
->overflow_time
);
261 if (pm1_sts
& val
& ACPI_BITMASK_TIMER_STATUS
) {
262 /* if TMRSTS is reset, then compute the new overflow time */
263 acpi_pm_tmr_calc_overflow_time(tmr
);
268 void acpi_pm1_evt_power_down(ACPIPM1EVT
*pm1
, ACPIPMTimer
*tmr
)
271 qemu_system_shutdown_request();
272 } else if (pm1
->en
& ACPI_BITMASK_POWER_BUTTON_ENABLE
) {
273 pm1
->sts
|= ACPI_BITMASK_POWER_BUTTON_STATUS
;
274 tmr
->update_sci(tmr
);
278 void acpi_pm1_evt_reset(ACPIPM1EVT
*pm1
)
285 void acpi_pm_tmr_update(ACPIPMTimer
*tmr
, bool enable
)
289 /* schedule a timer interruption if needed */
291 expire_time
= muldiv64(tmr
->overflow_time
, get_ticks_per_sec(),
293 qemu_mod_timer(tmr
->timer
, expire_time
);
295 qemu_del_timer(tmr
->timer
);
299 void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer
*tmr
)
301 int64_t d
= acpi_pm_tmr_get_clock();
302 tmr
->overflow_time
= (d
+ 0x800000LL
) & ~0x7fffffLL
;
305 uint32_t acpi_pm_tmr_get(ACPIPMTimer
*tmr
)
307 uint32_t d
= acpi_pm_tmr_get_clock();;
311 static void acpi_pm_tmr_timer(void *opaque
)
313 ACPIPMTimer
*tmr
= opaque
;
314 tmr
->update_sci(tmr
);
317 void acpi_pm_tmr_init(ACPIPMTimer
*tmr
, acpi_update_sci_fn update_sci
)
319 tmr
->update_sci
= update_sci
;
320 tmr
->timer
= qemu_new_timer_ns(vm_clock
, acpi_pm_tmr_timer
, tmr
);
323 void acpi_pm_tmr_reset(ACPIPMTimer
*tmr
)
325 tmr
->overflow_time
= 0;
326 qemu_del_timer(tmr
->timer
);
330 void acpi_pm1_cnt_init(ACPIPM1CNT
*pm1_cnt
, qemu_irq cmos_s3
)
332 pm1_cnt
->cmos_s3
= cmos_s3
;
335 void acpi_pm1_cnt_write(ACPIPM1EVT
*pm1a
, ACPIPM1CNT
*pm1_cnt
, uint16_t val
)
337 pm1_cnt
->cnt
= val
& ~(ACPI_BITMASK_SLEEP_ENABLE
);
339 if (val
& ACPI_BITMASK_SLEEP_ENABLE
) {
340 /* change suspend type */
341 uint16_t sus_typ
= (val
>> 10) & 7;
343 case 0: /* soft power off */
344 qemu_system_shutdown_request();
347 /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
348 Pretend that resume was caused by power button */
350 (ACPI_BITMASK_WAKE_STATUS
| ACPI_BITMASK_POWER_BUTTON_STATUS
);
351 qemu_system_reset_request();
352 qemu_irq_raise(pm1_cnt
->cmos_s3
);
359 void acpi_pm1_cnt_update(ACPIPM1CNT
*pm1_cnt
,
360 bool sci_enable
, bool sci_disable
)
362 /* ACPI specs 3.0, 4.7.2.5 */
364 pm1_cnt
->cnt
|= ACPI_BITMASK_SCI_ENABLE
;
365 } else if (sci_disable
) {
366 pm1_cnt
->cnt
&= ~ACPI_BITMASK_SCI_ENABLE
;
370 void acpi_pm1_cnt_reset(ACPIPM1CNT
*pm1_cnt
)
373 if (pm1_cnt
->cmos_s3
) {
374 qemu_irq_lower(pm1_cnt
->cmos_s3
);
379 void acpi_gpe_init(ACPIGPE
*gpe
, uint8_t len
)
382 gpe
->sts
= qemu_mallocz(len
/ 2);
383 gpe
->en
= qemu_mallocz(len
/ 2);
386 void acpi_gpe_blk(ACPIGPE
*gpe
, uint32_t blk
)
391 void acpi_gpe_reset(ACPIGPE
*gpe
)
393 memset(gpe
->sts
, 0, gpe
->len
/ 2);
394 memset(gpe
->en
, 0, gpe
->len
/ 2);
397 static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE
*gpe
, uint32_t addr
)
401 if (addr
< gpe
->len
/ 2) {
402 cur
= gpe
->sts
+ addr
;
403 } else if (addr
< gpe
->len
) {
404 cur
= gpe
->en
+ addr
- gpe
->len
/ 2;
412 void acpi_gpe_ioport_writeb(ACPIGPE
*gpe
, uint32_t addr
, uint32_t val
)
417 cur
= acpi_gpe_ioport_get_ptr(gpe
, addr
);
418 if (addr
< gpe
->len
/ 2) {
420 *cur
= (*cur
) & ~val
;
421 } else if (addr
< gpe
->len
) {
429 uint32_t acpi_gpe_ioport_readb(ACPIGPE
*gpe
, uint32_t addr
)
435 cur
= acpi_gpe_ioport_get_ptr(gpe
, addr
);