2
0

acpi.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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. {
  24. char signature [4]; /* ACPI signature (4 ASCII characters) */
  25. uint32_t length; /* Length of table, in bytes, including header */
  26. uint8_t revision; /* ACPI Specification minor version # */
  27. uint8_t checksum; /* To make sum of entire table == 0 */
  28. char oem_id [6]; /* OEM identification */
  29. char oem_table_id [8]; /* OEM table identification */
  30. uint32_t oem_revision; /* OEM revision number */
  31. char asl_compiler_id [4]; /* ASL compiler vendor ID */
  32. uint32_t asl_compiler_revision; /* ASL compiler revision number */
  33. } __attribute__((packed));
  34. char *acpi_tables;
  35. size_t acpi_tables_len;
  36. static int acpi_checksum(const uint8_t *data, int len)
  37. {
  38. int sum, i;
  39. sum = 0;
  40. for(i = 0; i < len; i++)
  41. sum += data[i];
  42. return (-sum) & 0xff;
  43. }
  44. int acpi_table_add(const char *t)
  45. {
  46. static const char *dfl_id = "QEMUQEMU";
  47. char buf[1024], *p, *f;
  48. struct acpi_table_header acpi_hdr;
  49. unsigned long val;
  50. uint32_t length;
  51. struct acpi_table_header *acpi_hdr_p;
  52. size_t off;
  53. memset(&acpi_hdr, 0, sizeof(acpi_hdr));
  54. if (get_param_value(buf, sizeof(buf), "sig", t)) {
  55. strncpy(acpi_hdr.signature, buf, 4);
  56. } else {
  57. strncpy(acpi_hdr.signature, dfl_id, 4);
  58. }
  59. if (get_param_value(buf, sizeof(buf), "rev", t)) {
  60. val = strtoul(buf, &p, 10);
  61. if (val > 255 || *p != '\0')
  62. goto out;
  63. } else {
  64. val = 1;
  65. }
  66. acpi_hdr.revision = (int8_t)val;
  67. if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
  68. strncpy(acpi_hdr.oem_id, buf, 6);
  69. } else {
  70. strncpy(acpi_hdr.oem_id, dfl_id, 6);
  71. }
  72. if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
  73. strncpy(acpi_hdr.oem_table_id, buf, 8);
  74. } else {
  75. strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
  76. }
  77. if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
  78. val = strtol(buf, &p, 10);
  79. if(*p != '\0')
  80. goto out;
  81. } else {
  82. val = 1;
  83. }
  84. acpi_hdr.oem_revision = cpu_to_le32(val);
  85. if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
  86. strncpy(acpi_hdr.asl_compiler_id, buf, 4);
  87. } else {
  88. strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
  89. }
  90. if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
  91. val = strtol(buf, &p, 10);
  92. if(*p != '\0')
  93. goto out;
  94. } else {
  95. val = 1;
  96. }
  97. acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
  98. if (!get_param_value(buf, sizeof(buf), "data", t)) {
  99. buf[0] = '\0';
  100. }
  101. length = sizeof(acpi_hdr);
  102. f = buf;
  103. while (buf[0]) {
  104. struct stat s;
  105. char *n = strchr(f, ':');
  106. if (n)
  107. *n = '\0';
  108. if(stat(f, &s) < 0) {
  109. fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
  110. goto out;
  111. }
  112. length += s.st_size;
  113. if (!n)
  114. break;
  115. *n = ':';
  116. f = n + 1;
  117. }
  118. if (!acpi_tables) {
  119. acpi_tables_len = sizeof(uint16_t);
  120. acpi_tables = qemu_mallocz(acpi_tables_len);
  121. }
  122. acpi_tables = qemu_realloc(acpi_tables,
  123. acpi_tables_len + sizeof(uint16_t) + length);
  124. p = acpi_tables + acpi_tables_len;
  125. acpi_tables_len += sizeof(uint16_t) + length;
  126. *(uint16_t*)p = cpu_to_le32(length);
  127. p += sizeof(uint16_t);
  128. memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
  129. off = sizeof(acpi_hdr);
  130. f = buf;
  131. while (buf[0]) {
  132. struct stat s;
  133. int fd;
  134. char *n = strchr(f, ':');
  135. if (n)
  136. *n = '\0';
  137. fd = open(f, O_RDONLY);
  138. if(fd < 0)
  139. goto out;
  140. if(fstat(fd, &s) < 0) {
  141. close(fd);
  142. goto out;
  143. }
  144. /* off < length is necessary because file size can be changed
  145. under our foot */
  146. while(s.st_size && off < length) {
  147. int r;
  148. r = read(fd, p + off, s.st_size);
  149. if (r > 0) {
  150. off += r;
  151. s.st_size -= r;
  152. } else if ((r < 0 && errno != EINTR) || r == 0) {
  153. close(fd);
  154. goto out;
  155. }
  156. }
  157. close(fd);
  158. if (!n)
  159. break;
  160. f = n + 1;
  161. }
  162. if (off < length) {
  163. /* don't pass random value in process to guest */
  164. memset(p + off, 0, length - off);
  165. }
  166. acpi_hdr_p = (struct acpi_table_header*)p;
  167. acpi_hdr_p->length = cpu_to_le32(length);
  168. acpi_hdr_p->checksum = acpi_checksum((uint8_t*)p, length);
  169. /* increase number of tables */
  170. (*(uint16_t*)acpi_tables) =
  171. cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
  172. return 0;
  173. out:
  174. if (acpi_tables) {
  175. qemu_free(acpi_tables);
  176. acpi_tables = NULL;
  177. }
  178. return -1;
  179. }
  180. /* ACPI PM1a EVT */
  181. uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time)
  182. {
  183. int64_t d = acpi_pm_tmr_get_clock();
  184. if (d >= overflow_time) {
  185. pm1->sts |= ACPI_BITMASK_TIMER_STATUS;
  186. }
  187. return pm1->sts;
  188. }
  189. void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val)
  190. {
  191. uint16_t pm1_sts = acpi_pm1_evt_get_sts(pm1, tmr->overflow_time);
  192. if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
  193. /* if TMRSTS is reset, then compute the new overflow time */
  194. acpi_pm_tmr_calc_overflow_time(tmr);
  195. }
  196. pm1->sts &= ~val;
  197. }
  198. void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr)
  199. {
  200. if (!pm1) {
  201. qemu_system_shutdown_request();
  202. } else if (pm1->en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
  203. pm1->sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
  204. tmr->update_sci(tmr);
  205. }
  206. }
  207. void acpi_pm1_evt_reset(ACPIPM1EVT *pm1)
  208. {
  209. pm1->sts = 0;
  210. pm1->en = 0;
  211. }
  212. /* ACPI PM_TMR */
  213. void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
  214. {
  215. int64_t expire_time;
  216. /* schedule a timer interruption if needed */
  217. if (enable) {
  218. expire_time = muldiv64(tmr->overflow_time, get_ticks_per_sec(),
  219. PM_TIMER_FREQUENCY);
  220. qemu_mod_timer(tmr->timer, expire_time);
  221. } else {
  222. qemu_del_timer(tmr->timer);
  223. }
  224. }
  225. void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
  226. {
  227. int64_t d = acpi_pm_tmr_get_clock();
  228. tmr->overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
  229. }
  230. uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
  231. {
  232. uint32_t d = acpi_pm_tmr_get_clock();;
  233. return d & 0xffffff;
  234. }
  235. static void acpi_pm_tmr_timer(void *opaque)
  236. {
  237. ACPIPMTimer *tmr = opaque;
  238. tmr->update_sci(tmr);
  239. }
  240. void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci)
  241. {
  242. tmr->update_sci = update_sci;
  243. tmr->timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, tmr);
  244. }
  245. void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
  246. {
  247. tmr->overflow_time = 0;
  248. qemu_del_timer(tmr->timer);
  249. }
  250. /* ACPI PM1aCNT */
  251. void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3)
  252. {
  253. pm1_cnt->cmos_s3 = cmos_s3;
  254. }
  255. void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val)
  256. {
  257. pm1_cnt->cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
  258. if (val & ACPI_BITMASK_SLEEP_ENABLE) {
  259. /* change suspend type */
  260. uint16_t sus_typ = (val >> 10) & 7;
  261. switch(sus_typ) {
  262. case 0: /* soft power off */
  263. qemu_system_shutdown_request();
  264. break;
  265. case 1:
  266. /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
  267. Pretend that resume was caused by power button */
  268. pm1a->sts |=
  269. (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
  270. qemu_system_reset_request();
  271. qemu_irq_raise(pm1_cnt->cmos_s3);
  272. default:
  273. break;
  274. }
  275. }
  276. }
  277. void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
  278. bool sci_enable, bool sci_disable)
  279. {
  280. /* ACPI specs 3.0, 4.7.2.5 */
  281. if (sci_enable) {
  282. pm1_cnt->cnt |= ACPI_BITMASK_SCI_ENABLE;
  283. } else if (sci_disable) {
  284. pm1_cnt->cnt &= ~ACPI_BITMASK_SCI_ENABLE;
  285. }
  286. }
  287. void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
  288. {
  289. pm1_cnt->cnt = 0;
  290. if (pm1_cnt->cmos_s3) {
  291. qemu_irq_lower(pm1_cnt->cmos_s3);
  292. }
  293. }
  294. /* ACPI GPE */
  295. void acpi_gpe_init(ACPIGPE *gpe, uint8_t len)
  296. {
  297. gpe->len = len;
  298. gpe->sts = qemu_mallocz(len / 2);
  299. gpe->en = qemu_mallocz(len / 2);
  300. }
  301. void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk)
  302. {
  303. gpe->blk = blk;
  304. }
  305. void acpi_gpe_reset(ACPIGPE *gpe)
  306. {
  307. memset(gpe->sts, 0, gpe->len / 2);
  308. memset(gpe->en, 0, gpe->len / 2);
  309. }
  310. static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
  311. {
  312. uint8_t *cur = NULL;
  313. if (addr < gpe->len / 2) {
  314. cur = gpe->sts + addr;
  315. } else if (addr < gpe->len) {
  316. cur = gpe->en + addr - gpe->len / 2;
  317. } else {
  318. abort();
  319. }
  320. return cur;
  321. }
  322. void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
  323. {
  324. uint8_t *cur;
  325. addr -= gpe->blk;
  326. cur = acpi_gpe_ioport_get_ptr(gpe, addr);
  327. if (addr < gpe->len / 2) {
  328. /* GPE_STS */
  329. *cur = (*cur) & ~val;
  330. } else if (addr < gpe->len) {
  331. /* GPE_EN */
  332. *cur = val;
  333. } else {
  334. abort();
  335. }
  336. }
  337. uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr)
  338. {
  339. uint8_t *cur;
  340. uint32_t val;
  341. addr -= gpe->blk;
  342. cur = acpi_gpe_ioport_get_ptr(gpe, addr);
  343. val = 0;
  344. if (cur != NULL) {
  345. val = *cur;
  346. }
  347. return val;
  348. }