Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

acpi.c 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <errno.h>
  25. #include <byteswap.h>
  26. #include <ipxe/uaccess.h>
  27. #include <ipxe/acpi.h>
  28. #include <ipxe/interface.h>
  29. /** @file
  30. *
  31. * ACPI support functions
  32. *
  33. */
  34. /******************************************************************************
  35. *
  36. * Utility functions
  37. *
  38. ******************************************************************************
  39. */
  40. /**
  41. * Fix up ACPI table checksum
  42. *
  43. * @v acpi ACPI table header
  44. */
  45. void acpi_fix_checksum ( struct acpi_header *acpi ) {
  46. unsigned int i = 0;
  47. uint8_t sum = 0;
  48. for ( i = 0 ; i < acpi->length ; i++ ) {
  49. sum += *( ( ( uint8_t * ) acpi ) + i );
  50. }
  51. acpi->checksum -= sum;
  52. }
  53. /**
  54. * Locate ACPI table
  55. *
  56. * @v signature Requested table signature
  57. * @v index Requested index of table with this signature
  58. * @ret table Table, or UNULL if not found
  59. */
  60. userptr_t acpi_find ( uint32_t signature, unsigned int index ) {
  61. struct acpi_header acpi;
  62. struct acpi_rsdt *rsdtab;
  63. typeof ( rsdtab->entry[0] ) entry;
  64. userptr_t rsdt;
  65. userptr_t table;
  66. size_t len;
  67. unsigned int count;
  68. unsigned int i;
  69. /* Locate RSDT */
  70. rsdt = acpi_find_rsdt();
  71. if ( ! rsdt ) {
  72. DBG ( "RSDT not found\n" );
  73. return UNULL;
  74. }
  75. /* Read RSDT header */
  76. copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
  77. if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
  78. DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
  79. user_to_phys ( rsdt, 0 ) );
  80. DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
  81. sizeof ( acpi ) );
  82. return UNULL;
  83. }
  84. len = le32_to_cpu ( acpi.length );
  85. if ( len < sizeof ( rsdtab->acpi ) ) {
  86. DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
  87. user_to_phys ( rsdt, 0 ) );
  88. DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
  89. sizeof ( acpi ) );
  90. return UNULL;
  91. }
  92. /* Calculate number of entries */
  93. count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );
  94. /* Search through entries */
  95. for ( i = 0 ; i < count ; i++ ) {
  96. /* Get table address */
  97. copy_from_user ( &entry, rsdt,
  98. offsetof ( typeof ( *rsdtab ), entry[i] ),
  99. sizeof ( entry ) );
  100. /* Read table header */
  101. table = phys_to_user ( entry );
  102. copy_from_user ( &acpi.signature, table, 0,
  103. sizeof ( acpi.signature ) );
  104. /* Check table signature */
  105. if ( acpi.signature != cpu_to_le32 ( signature ) )
  106. continue;
  107. /* Check index */
  108. if ( index-- )
  109. continue;
  110. DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
  111. user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
  112. user_to_phys ( table, 0 ) );
  113. return table;
  114. }
  115. DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
  116. user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
  117. return UNULL;
  118. }
  119. /**
  120. * Extract \_Sx value from DSDT/SSDT
  121. *
  122. * @v zsdt DSDT or SSDT
  123. * @v signature Signature (e.g. "_S5_")
  124. * @ret sx \_Sx value, or negative error
  125. *
  126. * In theory, extracting the \_Sx value from the DSDT/SSDT requires a
  127. * full ACPI parser plus some heuristics to work around the various
  128. * broken encodings encountered in real ACPI implementations.
  129. *
  130. * In practice, we can get the same result by scanning through the
  131. * DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first
  132. * four bytes, removing any bytes with bit 3 set, and treating
  133. * whatever is left as a little-endian value. This is one of the
  134. * uglier hacks I have ever implemented, but it's still prettier than
  135. * the ACPI specification itself.
  136. */
  137. static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
  138. struct acpi_header acpi;
  139. union {
  140. uint32_t dword;
  141. uint8_t byte[4];
  142. } buf;
  143. size_t offset;
  144. size_t len;
  145. unsigned int sx;
  146. uint8_t *byte;
  147. /* Read table header */
  148. copy_from_user ( &acpi, zsdt, 0, sizeof ( acpi ) );
  149. len = le32_to_cpu ( acpi.length );
  150. /* Locate signature */
  151. for ( offset = sizeof ( acpi ) ;
  152. ( ( offset + sizeof ( buf ) /* signature */ + 3 /* pkg header */
  153. + sizeof ( buf ) /* value */ ) < len ) ;
  154. offset++ ) {
  155. /* Check signature */
  156. copy_from_user ( &buf, zsdt, offset, sizeof ( buf ) );
  157. if ( buf.dword != cpu_to_le32 ( signature ) )
  158. continue;
  159. DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
  160. user_to_phys ( zsdt, 0 ), acpi_name ( signature ),
  161. offset );
  162. offset += sizeof ( buf );
  163. /* Read first four bytes of value */
  164. copy_from_user ( &buf, zsdt, ( offset + 3 /* pkg header */ ),
  165. sizeof ( buf ) );
  166. DBGC ( zsdt, "DSDT/SSDT %#08lx found %s containing "
  167. "%02x:%02x:%02x:%02x\n", user_to_phys ( zsdt, 0 ),
  168. acpi_name ( signature ), buf.byte[0], buf.byte[1],
  169. buf.byte[2], buf.byte[3] );
  170. /* Extract \Sx value. There are three potential
  171. * encodings that we might encounter:
  172. *
  173. * - SLP_TYPa, SLP_TYPb, rsvd, rsvd
  174. *
  175. * - <byteprefix>, SLP_TYPa, <byteprefix>, SLP_TYPb, ...
  176. *
  177. * - <dwordprefix>, SLP_TYPa, SLP_TYPb, 0, 0
  178. *
  179. * Since <byteprefix> and <dwordprefix> both have bit
  180. * 3 set, and valid SLP_TYPx must have bit 3 clear
  181. * (since SLP_TYPx is a 3-bit field), we can just skip
  182. * any bytes with bit 3 set.
  183. */
  184. byte = &buf.byte[0];
  185. if ( *byte & 0x08 )
  186. byte++;
  187. sx = *(byte++);
  188. if ( *byte & 0x08 )
  189. byte++;
  190. sx |= ( *byte << 8 );
  191. return sx;
  192. }
  193. return -ENOENT;
  194. }
  195. /**
  196. * Extract \_Sx value from DSDT/SSDT
  197. *
  198. * @v signature Signature (e.g. "_S5_")
  199. * @ret sx \_Sx value, or negative error
  200. */
  201. int acpi_sx ( uint32_t signature ) {
  202. struct acpi_fadt fadtab;
  203. userptr_t rsdt;
  204. userptr_t fadt;
  205. userptr_t dsdt;
  206. userptr_t ssdt;
  207. unsigned int i;
  208. int sx;
  209. /* Locate RSDT */
  210. rsdt = acpi_find_rsdt();
  211. if ( ! rsdt ) {
  212. DBG ( "RSDT not found\n" );
  213. return -ENOENT;
  214. }
  215. /* Try DSDT first */
  216. fadt = acpi_find ( FADT_SIGNATURE, 0 );
  217. if ( fadt ) {
  218. copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
  219. dsdt = phys_to_user ( fadtab.dsdt );
  220. if ( ( sx = acpi_sx_zsdt ( dsdt, signature ) ) >= 0 )
  221. return sx;
  222. }
  223. /* Try all SSDTs */
  224. for ( i = 0 ; ; i++ ) {
  225. ssdt = acpi_find ( SSDT_SIGNATURE, i );
  226. if ( ! ssdt )
  227. break;
  228. if ( ( sx = acpi_sx_zsdt ( ssdt, signature ) ) >= 0 )
  229. return sx;
  230. }
  231. DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
  232. user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
  233. return -ENOENT;
  234. }
  235. /******************************************************************************
  236. *
  237. * Descriptors
  238. *
  239. ******************************************************************************
  240. */
  241. /**
  242. * Add ACPI descriptor
  243. *
  244. * @v desc ACPI descriptor
  245. */
  246. void acpi_add ( struct acpi_descriptor *desc ) {
  247. /* Add to list of descriptors */
  248. ref_get ( desc->refcnt );
  249. list_add_tail ( &desc->list, &desc->model->descs );
  250. }
  251. /**
  252. * Remove ACPI descriptor
  253. *
  254. * @v desc ACPI descriptor
  255. */
  256. void acpi_del ( struct acpi_descriptor *desc ) {
  257. /* Remove from list of descriptors */
  258. list_check_contains_entry ( desc, &desc->model->descs, list );
  259. list_del ( &desc->list );
  260. ref_put ( desc->refcnt );
  261. }
  262. /**
  263. * Get object's ACPI descriptor
  264. *
  265. * @v intf Interface
  266. * @ret desc ACPI descriptor, or NULL
  267. */
  268. struct acpi_descriptor * acpi_describe ( struct interface *intf ) {
  269. struct interface *dest;
  270. acpi_describe_TYPE ( void * ) *op =
  271. intf_get_dest_op ( intf, acpi_describe, &dest );
  272. void *object = intf_object ( dest );
  273. struct acpi_descriptor *desc;
  274. if ( op ) {
  275. desc = op ( object );
  276. } else {
  277. desc = NULL;
  278. }
  279. intf_put ( dest );
  280. return desc;
  281. }
  282. /**
  283. * Install ACPI tables
  284. *
  285. * @v install Table installation method
  286. * @ret rc Return status code
  287. */
  288. int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ){
  289. struct acpi_model *model;
  290. int rc;
  291. for_each_table_entry ( model, ACPI_MODELS ) {
  292. if ( ( rc = model->install ( install ) ) != 0 )
  293. return rc;
  294. }
  295. return 0;
  296. }