oslinuxtbl.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. /******************************************************************************
  2. *
  3. * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2014, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include "acpidump.h"
  43. #define _COMPONENT ACPI_OS_SERVICES
  44. ACPI_MODULE_NAME("oslinuxtbl")
  45. #ifndef PATH_MAX
  46. #define PATH_MAX 256
  47. #endif
  48. /* List of information about obtained ACPI tables */
  49. typedef struct osl_table_info {
  50. struct osl_table_info *next;
  51. u32 instance;
  52. char signature[ACPI_NAME_SIZE];
  53. } osl_table_info;
  54. /* Local prototypes */
  55. static acpi_status osl_table_initialize(void);
  56. static acpi_status
  57. osl_table_name_from_file(char *filename, char *signature, u32 *instance);
  58. static acpi_status osl_add_table_to_list(char *signature, u32 instance);
  59. static acpi_status
  60. osl_read_table_from_file(char *filename,
  61. acpi_size file_offset,
  62. char *signature, struct acpi_table_header **table);
  63. static acpi_status
  64. osl_map_table(acpi_size address,
  65. char *signature, struct acpi_table_header **table);
  66. static void osl_unmap_table(struct acpi_table_header *table);
  67. static acpi_physical_address osl_find_rsdp_via_efi(void);
  68. static acpi_status osl_load_rsdp(void);
  69. static acpi_status osl_list_customized_tables(char *directory);
  70. static acpi_status
  71. osl_get_customized_table(char *pathname,
  72. char *signature,
  73. u32 instance,
  74. struct acpi_table_header **table,
  75. acpi_physical_address * address);
  76. static acpi_status osl_list_bios_tables(void);
  77. static acpi_status
  78. osl_get_bios_table(char *signature,
  79. u32 instance,
  80. struct acpi_table_header **table,
  81. acpi_physical_address * address);
  82. static acpi_status osl_get_last_status(acpi_status default_status);
  83. /* File locations */
  84. #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
  85. #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
  86. #define EFI_SYSTAB "/sys/firmware/efi/systab"
  87. /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
  88. u8 gbl_dump_dynamic_tables = TRUE;
  89. /* Initialization flags */
  90. u8 gbl_table_list_initialized = FALSE;
  91. /* Local copies of main ACPI tables */
  92. struct acpi_table_rsdp gbl_rsdp;
  93. struct acpi_table_fadt *gbl_fadt = NULL;
  94. struct acpi_table_rsdt *gbl_rsdt = NULL;
  95. struct acpi_table_xsdt *gbl_xsdt = NULL;
  96. /* Table addresses */
  97. acpi_physical_address gbl_fadt_address = 0;
  98. acpi_physical_address gbl_rsdp_address = 0;
  99. /* Revision of RSD PTR */
  100. u8 gbl_revision = 0;
  101. struct osl_table_info *gbl_table_list_head = NULL;
  102. u32 gbl_table_count = 0;
  103. /******************************************************************************
  104. *
  105. * FUNCTION: osl_get_last_status
  106. *
  107. * PARAMETERS: default_status - Default error status to return
  108. *
  109. * RETURN: Status; Converted from errno.
  110. *
  111. * DESCRIPTION: Get last errno and conver it to acpi_status.
  112. *
  113. *****************************************************************************/
  114. static acpi_status osl_get_last_status(acpi_status default_status)
  115. {
  116. switch (errno) {
  117. case EACCES:
  118. case EPERM:
  119. return (AE_ACCESS);
  120. case ENOENT:
  121. return (AE_NOT_FOUND);
  122. case ENOMEM:
  123. return (AE_NO_MEMORY);
  124. default:
  125. return (default_status);
  126. }
  127. }
  128. /******************************************************************************
  129. *
  130. * FUNCTION: acpi_os_get_table_by_address
  131. *
  132. * PARAMETERS: address - Physical address of the ACPI table
  133. * table - Where a pointer to the table is returned
  134. *
  135. * RETURN: Status; Table buffer is returned if AE_OK.
  136. * AE_NOT_FOUND: A valid table was not found at the address
  137. *
  138. * DESCRIPTION: Get an ACPI table via a physical memory address.
  139. *
  140. *****************************************************************************/
  141. acpi_status
  142. acpi_os_get_table_by_address(acpi_physical_address address,
  143. struct acpi_table_header ** table)
  144. {
  145. u32 table_length;
  146. struct acpi_table_header *mapped_table;
  147. struct acpi_table_header *local_table = NULL;
  148. acpi_status status = AE_OK;
  149. /* Get main ACPI tables from memory on first invocation of this function */
  150. status = osl_table_initialize();
  151. if (ACPI_FAILURE(status)) {
  152. return (status);
  153. }
  154. /* Map the table and validate it */
  155. status = osl_map_table(address, NULL, &mapped_table);
  156. if (ACPI_FAILURE(status)) {
  157. return (status);
  158. }
  159. /* Copy table to local buffer and return it */
  160. table_length = ap_get_table_length(mapped_table);
  161. if (table_length == 0) {
  162. status = AE_BAD_HEADER;
  163. goto exit;
  164. }
  165. local_table = calloc(1, table_length);
  166. if (!local_table) {
  167. status = AE_NO_MEMORY;
  168. goto exit;
  169. }
  170. ACPI_MEMCPY(local_table, mapped_table, table_length);
  171. exit:
  172. osl_unmap_table(mapped_table);
  173. *table = local_table;
  174. return (status);
  175. }
  176. /******************************************************************************
  177. *
  178. * FUNCTION: acpi_os_get_table_by_name
  179. *
  180. * PARAMETERS: signature - ACPI Signature for desired table. Must be
  181. * a null terminated 4-character string.
  182. * instance - Multiple table support for SSDT/UEFI (0...n)
  183. * Must be 0 for other tables.
  184. * table - Where a pointer to the table is returned
  185. * address - Where the table physical address is returned
  186. *
  187. * RETURN: Status; Table buffer and physical address returned if AE_OK.
  188. * AE_LIMIT: Instance is beyond valid limit
  189. * AE_NOT_FOUND: A table with the signature was not found
  190. *
  191. * NOTE: Assumes the input signature is uppercase.
  192. *
  193. *****************************************************************************/
  194. acpi_status
  195. acpi_os_get_table_by_name(char *signature,
  196. u32 instance,
  197. struct acpi_table_header ** table,
  198. acpi_physical_address * address)
  199. {
  200. acpi_status status;
  201. /* Get main ACPI tables from memory on first invocation of this function */
  202. status = osl_table_initialize();
  203. if (ACPI_FAILURE(status)) {
  204. return (status);
  205. }
  206. /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
  207. if (!gbl_dump_customized_tables) {
  208. /* Attempt to get the table from the memory */
  209. status =
  210. osl_get_bios_table(signature, instance, table, address);
  211. } else {
  212. /* Attempt to get the table from the static directory */
  213. status = osl_get_customized_table(STATIC_TABLE_DIR, signature,
  214. instance, table, address);
  215. }
  216. if (ACPI_FAILURE(status) && status == AE_LIMIT) {
  217. if (gbl_dump_dynamic_tables) {
  218. /* Attempt to get a dynamic table */
  219. status =
  220. osl_get_customized_table(DYNAMIC_TABLE_DIR,
  221. signature, instance, table,
  222. address);
  223. }
  224. }
  225. return (status);
  226. }
  227. /******************************************************************************
  228. *
  229. * FUNCTION: osl_add_table_to_list
  230. *
  231. * PARAMETERS: signature - Table signature
  232. * instance - Table instance
  233. *
  234. * RETURN: Status; Successfully added if AE_OK.
  235. * AE_NO_MEMORY: Memory allocation error
  236. *
  237. * DESCRIPTION: Insert a table structure into OSL table list.
  238. *
  239. *****************************************************************************/
  240. static acpi_status osl_add_table_to_list(char *signature, u32 instance)
  241. {
  242. struct osl_table_info *new_info;
  243. struct osl_table_info *next;
  244. u32 next_instance = 0;
  245. u8 found = FALSE;
  246. new_info = calloc(1, sizeof(struct osl_table_info));
  247. if (!new_info) {
  248. return (AE_NO_MEMORY);
  249. }
  250. ACPI_MOVE_NAME(new_info->signature, signature);
  251. if (!gbl_table_list_head) {
  252. gbl_table_list_head = new_info;
  253. } else {
  254. next = gbl_table_list_head;
  255. while (1) {
  256. if (ACPI_COMPARE_NAME(next->signature, signature)) {
  257. if (next->instance == instance) {
  258. found = TRUE;
  259. }
  260. if (next->instance >= next_instance) {
  261. next_instance = next->instance + 1;
  262. }
  263. }
  264. if (!next->next) {
  265. break;
  266. }
  267. next = next->next;
  268. }
  269. next->next = new_info;
  270. }
  271. if (found) {
  272. if (instance) {
  273. fprintf(stderr,
  274. "%4.4s: Warning unmatched table instance %d, expected %d\n",
  275. signature, instance, next_instance);
  276. }
  277. instance = next_instance;
  278. }
  279. new_info->instance = instance;
  280. gbl_table_count++;
  281. return (AE_OK);
  282. }
  283. /******************************************************************************
  284. *
  285. * FUNCTION: acpi_os_get_table_by_index
  286. *
  287. * PARAMETERS: index - Which table to get
  288. * table - Where a pointer to the table is returned
  289. * instance - Where a pointer to the table instance no. is
  290. * returned
  291. * address - Where the table physical address is returned
  292. *
  293. * RETURN: Status; Table buffer and physical address returned if AE_OK.
  294. * AE_LIMIT: Index is beyond valid limit
  295. *
  296. * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
  297. * AE_LIMIT when an invalid index is reached. Index is not
  298. * necessarily an index into the RSDT/XSDT.
  299. *
  300. *****************************************************************************/
  301. acpi_status
  302. acpi_os_get_table_by_index(u32 index,
  303. struct acpi_table_header ** table,
  304. u32 *instance, acpi_physical_address * address)
  305. {
  306. struct osl_table_info *info;
  307. acpi_status status;
  308. u32 i;
  309. /* Get main ACPI tables from memory on first invocation of this function */
  310. status = osl_table_initialize();
  311. if (ACPI_FAILURE(status)) {
  312. return (status);
  313. }
  314. /* Validate Index */
  315. if (index >= gbl_table_count) {
  316. return (AE_LIMIT);
  317. }
  318. /* Point to the table list entry specified by the Index argument */
  319. info = gbl_table_list_head;
  320. for (i = 0; i < index; i++) {
  321. info = info->next;
  322. }
  323. /* Now we can just get the table via the signature */
  324. status = acpi_os_get_table_by_name(info->signature, info->instance,
  325. table, address);
  326. if (ACPI_SUCCESS(status)) {
  327. *instance = info->instance;
  328. }
  329. return (status);
  330. }
  331. /******************************************************************************
  332. *
  333. * FUNCTION: osl_find_rsdp_via_efi
  334. *
  335. * PARAMETERS: None
  336. *
  337. * RETURN: RSDP address if found
  338. *
  339. * DESCRIPTION: Find RSDP address via EFI.
  340. *
  341. *****************************************************************************/
  342. static acpi_physical_address osl_find_rsdp_via_efi(void)
  343. {
  344. FILE *file;
  345. char buffer[80];
  346. unsigned long address = 0;
  347. file = fopen(EFI_SYSTAB, "r");
  348. if (file) {
  349. while (fgets(buffer, 80, file)) {
  350. if (sscanf(buffer, "ACPI20=0x%lx", &address) == 1) {
  351. break;
  352. }
  353. }
  354. fclose(file);
  355. }
  356. return ((acpi_physical_address) (address));
  357. }
  358. /******************************************************************************
  359. *
  360. * FUNCTION: osl_load_rsdp
  361. *
  362. * PARAMETERS: None
  363. *
  364. * RETURN: Status
  365. *
  366. * DESCRIPTION: Scan and load RSDP.
  367. *
  368. *****************************************************************************/
  369. static acpi_status osl_load_rsdp(void)
  370. {
  371. struct acpi_table_header *mapped_table;
  372. u8 *rsdp_address;
  373. acpi_physical_address rsdp_base;
  374. acpi_size rsdp_size;
  375. /* Get RSDP from memory */
  376. rsdp_size = sizeof(struct acpi_table_rsdp);
  377. if (gbl_rsdp_base) {
  378. rsdp_base = gbl_rsdp_base;
  379. } else {
  380. rsdp_base = osl_find_rsdp_via_efi();
  381. }
  382. if (!rsdp_base) {
  383. rsdp_base = ACPI_HI_RSDP_WINDOW_BASE;
  384. rsdp_size = ACPI_HI_RSDP_WINDOW_SIZE;
  385. }
  386. rsdp_address = acpi_os_map_memory(rsdp_base, rsdp_size);
  387. if (!rsdp_address) {
  388. return (osl_get_last_status(AE_BAD_ADDRESS));
  389. }
  390. /* Search low memory for the RSDP */
  391. mapped_table = ACPI_CAST_PTR(struct acpi_table_header,
  392. acpi_tb_scan_memory_for_rsdp(rsdp_address,
  393. rsdp_size));
  394. if (!mapped_table) {
  395. acpi_os_unmap_memory(rsdp_address, rsdp_size);
  396. return (AE_NOT_FOUND);
  397. }
  398. gbl_rsdp_address =
  399. rsdp_base + (ACPI_CAST8(mapped_table) - rsdp_address);
  400. ACPI_MEMCPY(&gbl_rsdp, mapped_table, sizeof(struct acpi_table_rsdp));
  401. acpi_os_unmap_memory(rsdp_address, rsdp_size);
  402. return (AE_OK);
  403. }
  404. /******************************************************************************
  405. *
  406. * FUNCTION: osl_can_use_xsdt
  407. *
  408. * PARAMETERS: None
  409. *
  410. * RETURN: TRUE if XSDT is allowed to be used.
  411. *
  412. * DESCRIPTION: This function collects logic that can be used to determine if
  413. * XSDT should be used instead of RSDT.
  414. *
  415. *****************************************************************************/
  416. static u8 osl_can_use_xsdt(void)
  417. {
  418. if (gbl_revision && !acpi_gbl_do_not_use_xsdt) {
  419. return (TRUE);
  420. } else {
  421. return (FALSE);
  422. }
  423. }
  424. /******************************************************************************
  425. *
  426. * FUNCTION: osl_table_initialize
  427. *
  428. * PARAMETERS: None
  429. *
  430. * RETURN: Status
  431. *
  432. * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
  433. * local variables. Main ACPI tables include RSDT, FADT, RSDT,
  434. * and/or XSDT.
  435. *
  436. *****************************************************************************/
  437. static acpi_status osl_table_initialize(void)
  438. {
  439. acpi_status status;
  440. acpi_physical_address address;
  441. if (gbl_table_list_initialized) {
  442. return (AE_OK);
  443. }
  444. /* Get RSDP from memory */
  445. status = osl_load_rsdp();
  446. if (ACPI_FAILURE(status)) {
  447. return (status);
  448. }
  449. /* Get XSDT from memory */
  450. if (gbl_rsdp.revision && !gbl_do_not_dump_xsdt) {
  451. if (gbl_xsdt) {
  452. free(gbl_xsdt);
  453. gbl_xsdt = NULL;
  454. }
  455. gbl_revision = 2;
  456. status = osl_get_bios_table(ACPI_SIG_XSDT, 0,
  457. ACPI_CAST_PTR(struct
  458. acpi_table_header *,
  459. &gbl_xsdt), &address);
  460. if (ACPI_FAILURE(status)) {
  461. return (status);
  462. }
  463. }
  464. /* Get RSDT from memory */
  465. if (gbl_rsdp.rsdt_physical_address) {
  466. if (gbl_rsdt) {
  467. free(gbl_rsdt);
  468. gbl_rsdt = NULL;
  469. }
  470. status = osl_get_bios_table(ACPI_SIG_RSDT, 0,
  471. ACPI_CAST_PTR(struct
  472. acpi_table_header *,
  473. &gbl_rsdt), &address);
  474. if (ACPI_FAILURE(status)) {
  475. return (status);
  476. }
  477. }
  478. /* Get FADT from memory */
  479. if (gbl_fadt) {
  480. free(gbl_fadt);
  481. gbl_fadt = NULL;
  482. }
  483. status = osl_get_bios_table(ACPI_SIG_FADT, 0,
  484. ACPI_CAST_PTR(struct acpi_table_header *,
  485. &gbl_fadt),
  486. &gbl_fadt_address);
  487. if (ACPI_FAILURE(status)) {
  488. return (status);
  489. }
  490. if (!gbl_dump_customized_tables) {
  491. /* Add mandatory tables to global table list first */
  492. status = osl_add_table_to_list(ACPI_RSDP_NAME, 0);
  493. if (ACPI_FAILURE(status)) {
  494. return (status);
  495. }
  496. status = osl_add_table_to_list(ACPI_SIG_RSDT, 0);
  497. if (ACPI_FAILURE(status)) {
  498. return (status);
  499. }
  500. if (gbl_revision == 2) {
  501. status = osl_add_table_to_list(ACPI_SIG_XSDT, 0);
  502. if (ACPI_FAILURE(status)) {
  503. return (status);
  504. }
  505. }
  506. status = osl_add_table_to_list(ACPI_SIG_DSDT, 0);
  507. if (ACPI_FAILURE(status)) {
  508. return (status);
  509. }
  510. status = osl_add_table_to_list(ACPI_SIG_FACS, 0);
  511. if (ACPI_FAILURE(status)) {
  512. return (status);
  513. }
  514. /* Add all tables found in the memory */
  515. status = osl_list_bios_tables();
  516. if (ACPI_FAILURE(status)) {
  517. return (status);
  518. }
  519. } else {
  520. /* Add all tables found in the static directory */
  521. status = osl_list_customized_tables(STATIC_TABLE_DIR);
  522. if (ACPI_FAILURE(status)) {
  523. return (status);
  524. }
  525. }
  526. if (gbl_dump_dynamic_tables) {
  527. /* Add all dynamically loaded tables in the dynamic directory */
  528. status = osl_list_customized_tables(DYNAMIC_TABLE_DIR);
  529. if (ACPI_FAILURE(status)) {
  530. return (status);
  531. }
  532. }
  533. gbl_table_list_initialized = TRUE;
  534. return (AE_OK);
  535. }
  536. /******************************************************************************
  537. *
  538. * FUNCTION: osl_list_bios_tables
  539. *
  540. * PARAMETERS: None
  541. *
  542. * RETURN: Status; Table list is initialized if AE_OK.
  543. *
  544. * DESCRIPTION: Add ACPI tables to the table list from memory.
  545. *
  546. * NOTE: This works on Linux as table customization does not modify the
  547. * addresses stored in RSDP/RSDT/XSDT/FADT.
  548. *
  549. *****************************************************************************/
  550. static acpi_status osl_list_bios_tables(void)
  551. {
  552. struct acpi_table_header *mapped_table = NULL;
  553. u8 *table_data;
  554. u8 number_of_tables;
  555. u8 item_size;
  556. acpi_physical_address table_address = 0;
  557. acpi_status status = AE_OK;
  558. u32 i;
  559. if (osl_can_use_xsdt()) {
  560. item_size = sizeof(u64);
  561. table_data =
  562. ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header);
  563. number_of_tables =
  564. (u8)((gbl_xsdt->header.length -
  565. sizeof(struct acpi_table_header))
  566. / item_size);
  567. } else { /* Use RSDT if XSDT is not available */
  568. item_size = sizeof(u32);
  569. table_data =
  570. ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header);
  571. number_of_tables =
  572. (u8)((gbl_rsdt->header.length -
  573. sizeof(struct acpi_table_header))
  574. / item_size);
  575. }
  576. /* Search RSDT/XSDT for the requested table */
  577. for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
  578. if (osl_can_use_xsdt()) {
  579. table_address =
  580. (acpi_physical_address) (*ACPI_CAST64(table_data));
  581. } else {
  582. table_address =
  583. (acpi_physical_address) (*ACPI_CAST32(table_data));
  584. }
  585. /* Skip NULL entries in RSDT/XSDT */
  586. if (!table_address) {
  587. continue;
  588. }
  589. status = osl_map_table(table_address, NULL, &mapped_table);
  590. if (ACPI_FAILURE(status)) {
  591. return (status);
  592. }
  593. osl_add_table_to_list(mapped_table->signature, 0);
  594. osl_unmap_table(mapped_table);
  595. }
  596. return (AE_OK);
  597. }
  598. /******************************************************************************
  599. *
  600. * FUNCTION: osl_get_bios_table
  601. *
  602. * PARAMETERS: signature - ACPI Signature for common table. Must be
  603. * a null terminated 4-character string.
  604. * instance - Multiple table support for SSDT/UEFI (0...n)
  605. * Must be 0 for other tables.
  606. * table - Where a pointer to the table is returned
  607. * address - Where the table physical address is returned
  608. *
  609. * RETURN: Status; Table buffer and physical address returned if AE_OK.
  610. * AE_LIMIT: Instance is beyond valid limit
  611. * AE_NOT_FOUND: A table with the signature was not found
  612. *
  613. * DESCRIPTION: Get a BIOS provided ACPI table
  614. *
  615. * NOTE: Assumes the input signature is uppercase.
  616. *
  617. *****************************************************************************/
  618. static acpi_status
  619. osl_get_bios_table(char *signature,
  620. u32 instance,
  621. struct acpi_table_header **table,
  622. acpi_physical_address * address)
  623. {
  624. struct acpi_table_header *local_table = NULL;
  625. struct acpi_table_header *mapped_table = NULL;
  626. u8 *table_data;
  627. u8 number_of_tables;
  628. u8 item_size;
  629. u32 current_instance = 0;
  630. acpi_physical_address table_address = 0;
  631. u32 table_length = 0;
  632. acpi_status status = AE_OK;
  633. u32 i;
  634. /* Handle special tables whose addresses are not in RSDT/XSDT */
  635. if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) ||
  636. ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) ||
  637. ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
  638. ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
  639. ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
  640. if (instance > 0) {
  641. return (AE_LIMIT);
  642. }
  643. /*
  644. * Get the appropriate address, either 32-bit or 64-bit. Be very
  645. * careful about the FADT length and validate table addresses.
  646. * Note: The 64-bit addresses have priority.
  647. */
  648. if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
  649. if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
  650. gbl_fadt->Xdsdt) {
  651. table_address =
  652. (acpi_physical_address) gbl_fadt->Xdsdt;
  653. } else
  654. if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
  655. && gbl_fadt->dsdt) {
  656. table_address =
  657. (acpi_physical_address) gbl_fadt->dsdt;
  658. }
  659. } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
  660. if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
  661. gbl_fadt->Xfacs) {
  662. table_address =
  663. (acpi_physical_address) gbl_fadt->Xfacs;
  664. } else
  665. if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
  666. && gbl_fadt->facs) {
  667. table_address =
  668. (acpi_physical_address) gbl_fadt->facs;
  669. }
  670. } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
  671. if (!gbl_revision) {
  672. return (AE_BAD_SIGNATURE);
  673. }
  674. table_address =
  675. (acpi_physical_address) gbl_rsdp.
  676. xsdt_physical_address;
  677. } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
  678. table_address =
  679. (acpi_physical_address) gbl_rsdp.
  680. rsdt_physical_address;
  681. } else {
  682. table_address =
  683. (acpi_physical_address) gbl_rsdp_address;
  684. signature = ACPI_SIG_RSDP;
  685. }
  686. /* Now we can get the requested special table */
  687. status = osl_map_table(table_address, signature, &mapped_table);
  688. if (ACPI_FAILURE(status)) {
  689. return (status);
  690. }
  691. table_length = ap_get_table_length(mapped_table);
  692. } else { /* Case for a normal ACPI table */
  693. if (osl_can_use_xsdt()) {
  694. item_size = sizeof(u64);
  695. table_data =
  696. ACPI_CAST8(gbl_xsdt) +
  697. sizeof(struct acpi_table_header);
  698. number_of_tables =
  699. (u8)((gbl_xsdt->header.length -
  700. sizeof(struct acpi_table_header))
  701. / item_size);
  702. } else { /* Use RSDT if XSDT is not available */
  703. item_size = sizeof(u32);
  704. table_data =
  705. ACPI_CAST8(gbl_rsdt) +
  706. sizeof(struct acpi_table_header);
  707. number_of_tables =
  708. (u8)((gbl_rsdt->header.length -
  709. sizeof(struct acpi_table_header))
  710. / item_size);
  711. }
  712. /* Search RSDT/XSDT for the requested table */
  713. for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
  714. if (osl_can_use_xsdt()) {
  715. table_address =
  716. (acpi_physical_address) (*ACPI_CAST64
  717. (table_data));
  718. } else {
  719. table_address =
  720. (acpi_physical_address) (*ACPI_CAST32
  721. (table_data));
  722. }
  723. /* Skip NULL entries in RSDT/XSDT */
  724. if (!table_address) {
  725. continue;
  726. }
  727. status =
  728. osl_map_table(table_address, NULL, &mapped_table);
  729. if (ACPI_FAILURE(status)) {
  730. return (status);
  731. }
  732. table_length = mapped_table->length;
  733. /* Does this table match the requested signature? */
  734. if (!ACPI_COMPARE_NAME
  735. (mapped_table->signature, signature)) {
  736. osl_unmap_table(mapped_table);
  737. mapped_table = NULL;
  738. continue;
  739. }
  740. /* Match table instance (for SSDT/UEFI tables) */
  741. if (current_instance != instance) {
  742. osl_unmap_table(mapped_table);
  743. mapped_table = NULL;
  744. current_instance++;
  745. continue;
  746. }
  747. break;
  748. }
  749. }
  750. if (!mapped_table) {
  751. return (AE_LIMIT);
  752. }
  753. if (table_length == 0) {
  754. status = AE_BAD_HEADER;
  755. goto exit;
  756. }
  757. /* Copy table to local buffer and return it */
  758. local_table = calloc(1, table_length);
  759. if (!local_table) {
  760. status = AE_NO_MEMORY;
  761. goto exit;
  762. }
  763. ACPI_MEMCPY(local_table, mapped_table, table_length);
  764. *address = table_address;
  765. *table = local_table;
  766. exit:
  767. osl_unmap_table(mapped_table);
  768. return (status);
  769. }
  770. /******************************************************************************
  771. *
  772. * FUNCTION: osl_list_customized_tables
  773. *
  774. * PARAMETERS: directory - Directory that contains the tables
  775. *
  776. * RETURN: Status; Table list is initialized if AE_OK.
  777. *
  778. * DESCRIPTION: Add ACPI tables to the table list from a directory.
  779. *
  780. *****************************************************************************/
  781. static acpi_status osl_list_customized_tables(char *directory)
  782. {
  783. void *table_dir;
  784. u32 instance;
  785. char temp_name[ACPI_NAME_SIZE];
  786. char *filename;
  787. acpi_status status = AE_OK;
  788. /* Open the requested directory */
  789. table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY);
  790. if (!table_dir) {
  791. return (osl_get_last_status(AE_NOT_FOUND));
  792. }
  793. /* Examine all entries in this directory */
  794. while ((filename = acpi_os_get_next_filename(table_dir))) {
  795. /* Extract table name and instance number */
  796. status =
  797. osl_table_name_from_file(filename, temp_name, &instance);
  798. /* Ignore meaningless files */
  799. if (ACPI_FAILURE(status)) {
  800. continue;
  801. }
  802. /* Add new info node to global table list */
  803. status = osl_add_table_to_list(temp_name, instance);
  804. if (ACPI_FAILURE(status)) {
  805. break;
  806. }
  807. }
  808. acpi_os_close_directory(table_dir);
  809. return (status);
  810. }
  811. /******************************************************************************
  812. *
  813. * FUNCTION: osl_map_table
  814. *
  815. * PARAMETERS: address - Address of the table in memory
  816. * signature - Optional ACPI Signature for desired table.
  817. * Null terminated 4-character string.
  818. * table - Where a pointer to the mapped table is
  819. * returned
  820. *
  821. * RETURN: Status; Mapped table is returned if AE_OK.
  822. * AE_NOT_FOUND: A valid table was not found at the address
  823. *
  824. * DESCRIPTION: Map entire ACPI table into caller's address space.
  825. *
  826. *****************************************************************************/
  827. static acpi_status
  828. osl_map_table(acpi_size address,
  829. char *signature, struct acpi_table_header **table)
  830. {
  831. struct acpi_table_header *mapped_table;
  832. u32 length;
  833. if (!address) {
  834. return (AE_BAD_ADDRESS);
  835. }
  836. /*
  837. * Map the header so we can get the table length.
  838. * Use sizeof (struct acpi_table_header) as:
  839. * 1. it is bigger than 24 to include RSDP->Length
  840. * 2. it is smaller than sizeof (struct acpi_table_rsdp)
  841. */
  842. mapped_table =
  843. acpi_os_map_memory(address, sizeof(struct acpi_table_header));
  844. if (!mapped_table) {
  845. fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n",
  846. ACPI_FORMAT_UINT64(address));
  847. return (osl_get_last_status(AE_BAD_ADDRESS));
  848. }
  849. /* If specified, signature must match */
  850. if (signature) {
  851. if (ACPI_VALIDATE_RSDP_SIG(signature)) {
  852. if (!ACPI_VALIDATE_RSDP_SIG(mapped_table->signature)) {
  853. acpi_os_unmap_memory(mapped_table,
  854. sizeof(struct
  855. acpi_table_header));
  856. return (AE_BAD_SIGNATURE);
  857. }
  858. } else
  859. if (!ACPI_COMPARE_NAME(signature, mapped_table->signature))
  860. {
  861. acpi_os_unmap_memory(mapped_table,
  862. sizeof(struct acpi_table_header));
  863. return (AE_BAD_SIGNATURE);
  864. }
  865. }
  866. /* Map the entire table */
  867. length = ap_get_table_length(mapped_table);
  868. acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
  869. if (length == 0) {
  870. return (AE_BAD_HEADER);
  871. }
  872. mapped_table = acpi_os_map_memory(address, length);
  873. if (!mapped_table) {
  874. fprintf(stderr,
  875. "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
  876. ACPI_FORMAT_UINT64(address), length);
  877. return (osl_get_last_status(AE_INVALID_TABLE_LENGTH));
  878. }
  879. (void)ap_is_valid_checksum(mapped_table);
  880. *table = mapped_table;
  881. return (AE_OK);
  882. }
  883. /******************************************************************************
  884. *
  885. * FUNCTION: osl_unmap_table
  886. *
  887. * PARAMETERS: table - A pointer to the mapped table
  888. *
  889. * RETURN: None
  890. *
  891. * DESCRIPTION: Unmap entire ACPI table.
  892. *
  893. *****************************************************************************/
  894. static void osl_unmap_table(struct acpi_table_header *table)
  895. {
  896. if (table) {
  897. acpi_os_unmap_memory(table, ap_get_table_length(table));
  898. }
  899. }
  900. /******************************************************************************
  901. *
  902. * FUNCTION: osl_table_name_from_file
  903. *
  904. * PARAMETERS: filename - File that contains the desired table
  905. * signature - Pointer to 4-character buffer to store
  906. * extracted table signature.
  907. * instance - Pointer to integer to store extracted
  908. * table instance number.
  909. *
  910. * RETURN: Status; Table name is extracted if AE_OK.
  911. *
  912. * DESCRIPTION: Extract table signature and instance number from a table file
  913. * name.
  914. *
  915. *****************************************************************************/
  916. static acpi_status
  917. osl_table_name_from_file(char *filename, char *signature, u32 *instance)
  918. {
  919. /* Ignore meaningless files */
  920. if (strlen(filename) < ACPI_NAME_SIZE) {
  921. return (AE_BAD_SIGNATURE);
  922. }
  923. /* Extract instance number */
  924. if (isdigit((int)filename[ACPI_NAME_SIZE])) {
  925. sscanf(&filename[ACPI_NAME_SIZE], "%d", instance);
  926. } else if (strlen(filename) != ACPI_NAME_SIZE) {
  927. return (AE_BAD_SIGNATURE);
  928. } else {
  929. *instance = 0;
  930. }
  931. /* Extract signature */
  932. ACPI_MOVE_NAME(signature, filename);
  933. return (AE_OK);
  934. }
  935. /******************************************************************************
  936. *
  937. * FUNCTION: osl_read_table_from_file
  938. *
  939. * PARAMETERS: filename - File that contains the desired table
  940. * file_offset - Offset of the table in file
  941. * signature - Optional ACPI Signature for desired table.
  942. * A null terminated 4-character string.
  943. * table - Where a pointer to the table is returned
  944. *
  945. * RETURN: Status; Table buffer is returned if AE_OK.
  946. *
  947. * DESCRIPTION: Read a ACPI table from a file.
  948. *
  949. *****************************************************************************/
  950. static acpi_status
  951. osl_read_table_from_file(char *filename,
  952. acpi_size file_offset,
  953. char *signature, struct acpi_table_header **table)
  954. {
  955. FILE *table_file;
  956. struct acpi_table_header header;
  957. struct acpi_table_header *local_table = NULL;
  958. u32 table_length;
  959. s32 count;
  960. acpi_status status = AE_OK;
  961. /* Open the file */
  962. table_file = fopen(filename, "rb");
  963. if (table_file == NULL) {
  964. fprintf(stderr, "Could not open table file: %s\n", filename);
  965. return (osl_get_last_status(AE_NOT_FOUND));
  966. }
  967. fseek(table_file, file_offset, SEEK_SET);
  968. /* Read the Table header to get the table length */
  969. count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
  970. if (count != sizeof(struct acpi_table_header)) {
  971. fprintf(stderr, "Could not read table header: %s\n", filename);
  972. status = AE_BAD_HEADER;
  973. goto exit;
  974. }
  975. /* If signature is specified, it must match the table */
  976. if (signature) {
  977. if (ACPI_VALIDATE_RSDP_SIG(signature)) {
  978. if (!ACPI_VALIDATE_RSDP_SIG(header.signature)) {
  979. fprintf(stderr,
  980. "Incorrect RSDP signature: found %8.8s\n",
  981. header.signature);
  982. status = AE_BAD_SIGNATURE;
  983. goto exit;
  984. }
  985. } else if (!ACPI_COMPARE_NAME(signature, header.signature)) {
  986. fprintf(stderr,
  987. "Incorrect signature: Expecting %4.4s, found %4.4s\n",
  988. signature, header.signature);
  989. status = AE_BAD_SIGNATURE;
  990. goto exit;
  991. }
  992. }
  993. table_length = ap_get_table_length(&header);
  994. if (table_length == 0) {
  995. status = AE_BAD_HEADER;
  996. goto exit;
  997. }
  998. /* Read the entire table into a local buffer */
  999. local_table = calloc(1, table_length);
  1000. if (!local_table) {
  1001. fprintf(stderr,
  1002. "%4.4s: Could not allocate buffer for table of length %X\n",
  1003. header.signature, table_length);
  1004. status = AE_NO_MEMORY;
  1005. goto exit;
  1006. }
  1007. fseek(table_file, file_offset, SEEK_SET);
  1008. count = fread(local_table, 1, table_length, table_file);
  1009. if (count != table_length) {
  1010. fprintf(stderr, "%4.4s: Could not read table content\n",
  1011. header.signature);
  1012. status = AE_INVALID_TABLE_LENGTH;
  1013. goto exit;
  1014. }
  1015. /* Validate checksum */
  1016. (void)ap_is_valid_checksum(local_table);
  1017. exit:
  1018. fclose(table_file);
  1019. *table = local_table;
  1020. return (status);
  1021. }
  1022. /******************************************************************************
  1023. *
  1024. * FUNCTION: osl_get_customized_table
  1025. *
  1026. * PARAMETERS: pathname - Directory to find Linux customized table
  1027. * signature - ACPI Signature for desired table. Must be
  1028. * a null terminated 4-character string.
  1029. * instance - Multiple table support for SSDT/UEFI (0...n)
  1030. * Must be 0 for other tables.
  1031. * table - Where a pointer to the table is returned
  1032. * address - Where the table physical address is returned
  1033. *
  1034. * RETURN: Status; Table buffer is returned if AE_OK.
  1035. * AE_LIMIT: Instance is beyond valid limit
  1036. * AE_NOT_FOUND: A table with the signature was not found
  1037. *
  1038. * DESCRIPTION: Get an OS customized table.
  1039. *
  1040. *****************************************************************************/
  1041. static acpi_status
  1042. osl_get_customized_table(char *pathname,
  1043. char *signature,
  1044. u32 instance,
  1045. struct acpi_table_header **table,
  1046. acpi_physical_address * address)
  1047. {
  1048. void *table_dir;
  1049. u32 current_instance = 0;
  1050. char temp_name[ACPI_NAME_SIZE];
  1051. char table_filename[PATH_MAX];
  1052. char *filename;
  1053. acpi_status status;
  1054. /* Open the directory for customized tables */
  1055. table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
  1056. if (!table_dir) {
  1057. return (osl_get_last_status(AE_NOT_FOUND));
  1058. }
  1059. /* Attempt to find the table in the directory */
  1060. while ((filename = acpi_os_get_next_filename(table_dir))) {
  1061. /* Ignore meaningless files */
  1062. if (!ACPI_COMPARE_NAME(filename, signature)) {
  1063. continue;
  1064. }
  1065. /* Extract table name and instance number */
  1066. status =
  1067. osl_table_name_from_file(filename, temp_name,
  1068. &current_instance);
  1069. /* Ignore meaningless files */
  1070. if (ACPI_FAILURE(status) || current_instance != instance) {
  1071. continue;
  1072. }
  1073. /* Create the table pathname */
  1074. if (instance != 0) {
  1075. sprintf(table_filename, "%s/%4.4s%d", pathname,
  1076. temp_name, instance);
  1077. } else {
  1078. sprintf(table_filename, "%s/%4.4s", pathname,
  1079. temp_name);
  1080. }
  1081. break;
  1082. }
  1083. acpi_os_close_directory(table_dir);
  1084. if (!filename) {
  1085. return (AE_LIMIT);
  1086. }
  1087. /* There is no physical address saved for customized tables, use zero */
  1088. *address = 0;
  1089. status = osl_read_table_from_file(table_filename, 0, NULL, table);
  1090. return (status);
  1091. }