2
0

acpi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*
  2. * ACPI implementation
  3. *
  4. * Copyright (c) 2006 Fabrice Bellard
  5. *
  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.
  9. *
  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.
  14. *
  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/>
  17. */
  18. #include "sysemu.h"
  19. #include "hw.h"
  20. #include "pc.h"
  21. #include "acpi.h"
  22. struct acpi_table_header {
  23. uint16_t _length; /* our length, not actual part of the hdr */
  24. /* XXX why we have 2 length fields here? */
  25. char sig[4]; /* ACPI signature (4 ASCII characters) */
  26. uint32_t length; /* Length of table, in bytes, including header */
  27. uint8_t revision; /* ACPI Specification minor version # */
  28. uint8_t checksum; /* To make sum of entire table == 0 */
  29. char oem_id[6]; /* OEM identification */
  30. char oem_table_id[8]; /* OEM table identification */
  31. uint32_t oem_revision; /* OEM revision number */
  32. char asl_compiler_id[4]; /* ASL compiler vendor ID */
  33. uint32_t asl_compiler_revision; /* ASL compiler revision number */
  34. } QEMU_PACKED;
  35. #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
  36. #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */
  37. static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
  38. "\0\0" /* fake _length (2) */
  39. "QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */
  40. "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
  41. "QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */
  42. ;
  43. char *acpi_tables;
  44. size_t acpi_tables_len;
  45. static int acpi_checksum(const uint8_t *data, int len)
  46. {
  47. int sum, i;
  48. sum = 0;
  49. for (i = 0; i < len; i++) {
  50. sum += data[i];
  51. }
  52. return (-sum) & 0xff;
  53. }
  54. /* like strncpy() but zero-fills the tail of destination */
  55. static void strzcpy(char *dst, const char *src, size_t size)
  56. {
  57. size_t len = strlen(src);
  58. if (len >= size) {
  59. len = size;
  60. } else {
  61. memset(dst + len, 0, size - len);
  62. }
  63. memcpy(dst, src, len);
  64. }
  65. /* XXX fixme: this function uses obsolete argument parsing interface */
  66. int acpi_table_add(const char *t)
  67. {
  68. char buf[1024], *p, *f;
  69. unsigned long val;
  70. size_t len, start, allen;
  71. bool has_header;
  72. int changed;
  73. int r;
  74. struct acpi_table_header hdr;
  75. r = 0;
  76. r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
  77. r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
  78. switch (r) {
  79. case 0:
  80. buf[0] = '\0';
  81. /* fallthrough for default behavior */
  82. case 1:
  83. has_header = false;
  84. break;
  85. case 2:
  86. has_header = true;
  87. break;
  88. default:
  89. fprintf(stderr, "acpitable: both data and file are specified\n");
  90. return -1;
  91. }
  92. if (!acpi_tables) {
  93. allen = sizeof(uint16_t);
  94. acpi_tables = g_malloc0(allen);
  95. } else {
  96. allen = acpi_tables_len;
  97. }
  98. start = allen;
  99. acpi_tables = g_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
  100. allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
  101. /* now read in the data files, reallocating buffer as needed */
  102. for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
  103. int fd = open(f, O_RDONLY);
  104. if (fd < 0) {
  105. fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
  106. return -1;
  107. }
  108. for (;;) {
  109. char data[8192];
  110. r = read(fd, data, sizeof(data));
  111. if (r == 0) {
  112. break;
  113. } else if (r > 0) {
  114. acpi_tables = g_realloc(acpi_tables, allen + r);
  115. memcpy(acpi_tables + allen, data, r);
  116. allen += r;
  117. } else if (errno != EINTR) {
  118. fprintf(stderr, "can't read file %s: %s\n",
  119. f, strerror(errno));
  120. close(fd);
  121. return -1;
  122. }
  123. }
  124. close(fd);
  125. }
  126. /* now fill in the header fields */
  127. f = acpi_tables + start; /* start of the table */
  128. changed = 0;
  129. /* copy the header to temp place to align the fields */
  130. memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
  131. /* length of the table minus our prefix */
  132. len = allen - start - ACPI_TABLE_PFX_SIZE;
  133. hdr._length = cpu_to_le16(len);
  134. if (get_param_value(buf, sizeof(buf), "sig", t)) {
  135. strzcpy(hdr.sig, buf, sizeof(hdr.sig));
  136. ++changed;
  137. }
  138. /* length of the table including header, in bytes */
  139. if (has_header) {
  140. /* check if actual length is correct */
  141. val = le32_to_cpu(hdr.length);
  142. if (val != len) {
  143. fprintf(stderr,
  144. "warning: acpitable has wrong length,"
  145. " header says %lu, actual size %zu bytes\n",
  146. val, len);
  147. ++changed;
  148. }
  149. }
  150. /* we may avoid putting length here if has_header is true */
  151. hdr.length = cpu_to_le32(len);
  152. if (get_param_value(buf, sizeof(buf), "rev", t)) {
  153. val = strtoul(buf, &p, 0);
  154. if (val > 255 || *p) {
  155. fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
  156. return -1;
  157. }
  158. hdr.revision = (uint8_t)val;
  159. ++changed;
  160. }
  161. if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
  162. strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
  163. ++changed;
  164. }
  165. if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
  166. strzcpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
  167. ++changed;
  168. }
  169. if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
  170. val = strtol(buf, &p, 0);
  171. if (*p) {
  172. fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
  173. return -1;
  174. }
  175. hdr.oem_revision = cpu_to_le32(val);
  176. ++changed;
  177. }
  178. if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
  179. strzcpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
  180. ++changed;
  181. }
  182. if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
  183. val = strtol(buf, &p, 0);
  184. if (*p) {
  185. fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
  186. "asl_compiler_rev", buf);
  187. return -1;
  188. }
  189. hdr.asl_compiler_revision = cpu_to_le32(val);
  190. ++changed;
  191. }
  192. if (!has_header && !changed) {
  193. fprintf(stderr, "warning: acpitable: no table headers are specified\n");
  194. }
  195. /* now calculate checksum of the table, complete with the header */
  196. /* we may as well leave checksum intact if has_header is true */
  197. /* alternatively there may be a way to set cksum to a given value */
  198. hdr.checksum = 0; /* for checksum calculation */
  199. /* put header back */
  200. memcpy(f, &hdr, sizeof(hdr));
  201. if (changed || !has_header || 1) {
  202. ((struct acpi_table_header *)f)->checksum =
  203. acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
  204. }
  205. /* increase number of tables */
  206. (*(uint16_t *)acpi_tables) =
  207. cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
  208. acpi_tables_len = allen;
  209. return 0;
  210. }
  211. /* ACPI PM1a EVT */
  212. uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time)
  213. {
  214. int64_t d = acpi_pm_tmr_get_clock();
  215. if (d >= overflow_time) {
  216. pm1->sts |= ACPI_BITMASK_TIMER_STATUS;
  217. }
  218. return pm1->sts;
  219. }
  220. void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val)
  221. {
  222. uint16_t pm1_sts = acpi_pm1_evt_get_sts(pm1, tmr->overflow_time);
  223. if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
  224. /* if TMRSTS is reset, then compute the new overflow time */
  225. acpi_pm_tmr_calc_overflow_time(tmr);
  226. }
  227. pm1->sts &= ~val;
  228. }
  229. void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr)
  230. {
  231. if (!pm1) {
  232. qemu_system_shutdown_request();
  233. } else if (pm1->en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
  234. pm1->sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
  235. tmr->update_sci(tmr);
  236. }
  237. }
  238. void acpi_pm1_evt_reset(ACPIPM1EVT *pm1)
  239. {
  240. pm1->sts = 0;
  241. pm1->en = 0;
  242. }
  243. /* ACPI PM_TMR */
  244. void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
  245. {
  246. int64_t expire_time;
  247. /* schedule a timer interruption if needed */
  248. if (enable) {
  249. expire_time = muldiv64(tmr->overflow_time, get_ticks_per_sec(),
  250. PM_TIMER_FREQUENCY);
  251. qemu_mod_timer(tmr->timer, expire_time);
  252. } else {
  253. qemu_del_timer(tmr->timer);
  254. }
  255. }
  256. void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
  257. {
  258. int64_t d = acpi_pm_tmr_get_clock();
  259. tmr->overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
  260. }
  261. uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
  262. {
  263. uint32_t d = acpi_pm_tmr_get_clock();;
  264. return d & 0xffffff;
  265. }
  266. static void acpi_pm_tmr_timer(void *opaque)
  267. {
  268. ACPIPMTimer *tmr = opaque;
  269. tmr->update_sci(tmr);
  270. }
  271. void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci)
  272. {
  273. tmr->update_sci = update_sci;
  274. tmr->timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, tmr);
  275. }
  276. void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
  277. {
  278. tmr->overflow_time = 0;
  279. qemu_del_timer(tmr->timer);
  280. }
  281. /* ACPI PM1aCNT */
  282. void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3)
  283. {
  284. pm1_cnt->cmos_s3 = cmos_s3;
  285. }
  286. void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val)
  287. {
  288. pm1_cnt->cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
  289. if (val & ACPI_BITMASK_SLEEP_ENABLE) {
  290. /* change suspend type */
  291. uint16_t sus_typ = (val >> 10) & 7;
  292. switch(sus_typ) {
  293. case 0: /* soft power off */
  294. qemu_system_shutdown_request();
  295. break;
  296. case 1:
  297. /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
  298. Pretend that resume was caused by power button */
  299. pm1a->sts |=
  300. (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
  301. qemu_system_reset_request();
  302. qemu_irq_raise(pm1_cnt->cmos_s3);
  303. default:
  304. break;
  305. }
  306. }
  307. }
  308. void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
  309. bool sci_enable, bool sci_disable)
  310. {
  311. /* ACPI specs 3.0, 4.7.2.5 */
  312. if (sci_enable) {
  313. pm1_cnt->cnt |= ACPI_BITMASK_SCI_ENABLE;
  314. } else if (sci_disable) {
  315. pm1_cnt->cnt &= ~ACPI_BITMASK_SCI_ENABLE;
  316. }
  317. }
  318. void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
  319. {
  320. pm1_cnt->cnt = 0;
  321. if (pm1_cnt->cmos_s3) {
  322. qemu_irq_lower(pm1_cnt->cmos_s3);
  323. }
  324. }
  325. /* ACPI GPE */
  326. void acpi_gpe_init(ACPIGPE *gpe, uint8_t len)
  327. {
  328. gpe->len = len;
  329. gpe->sts = g_malloc0(len / 2);
  330. gpe->en = g_malloc0(len / 2);
  331. }
  332. void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk)
  333. {
  334. gpe->blk = blk;
  335. }
  336. void acpi_gpe_reset(ACPIGPE *gpe)
  337. {
  338. memset(gpe->sts, 0, gpe->len / 2);
  339. memset(gpe->en, 0, gpe->len / 2);
  340. }
  341. static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
  342. {
  343. uint8_t *cur = NULL;
  344. if (addr < gpe->len / 2) {
  345. cur = gpe->sts + addr;
  346. } else if (addr < gpe->len) {
  347. cur = gpe->en + addr - gpe->len / 2;
  348. } else {
  349. abort();
  350. }
  351. return cur;
  352. }
  353. void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
  354. {
  355. uint8_t *cur;
  356. addr -= gpe->blk;
  357. cur = acpi_gpe_ioport_get_ptr(gpe, addr);
  358. if (addr < gpe->len / 2) {
  359. /* GPE_STS */
  360. *cur = (*cur) & ~val;
  361. } else if (addr < gpe->len) {
  362. /* GPE_EN */
  363. *cur = val;
  364. } else {
  365. abort();
  366. }
  367. }
  368. uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr)
  369. {
  370. uint8_t *cur;
  371. uint32_t val;
  372. addr -= gpe->blk;
  373. cur = acpi_gpe_ioport_get_ptr(gpe, addr);
  374. val = 0;
  375. if (cur != NULL) {
  376. val = *cur;
  377. }
  378. return val;
  379. }