tbxfroot.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
  4.  *              $Revision: 52 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "achware.h"
  26. #include "actables.h"
  27. #define _COMPONENT          ACPI_TABLES
  28.  MODULE_NAME         ("tbxfroot")
  29. #define RSDP_CHECKSUM_LENGTH 20
  30. /*******************************************************************************
  31.  *
  32.  * FUNCTION:    Acpi_find_root_pointer
  33.  *
  34.  * PARAMETERS:  **Rsdp_physical_address     - Where to place the RSDP address
  35.  *              Flags                       - Logical/Physical addressing
  36.  *
  37.  * RETURN:      Status, Physical address of the RSDP
  38.  *
  39.  * DESCRIPTION: Find the RSDP
  40.  *
  41.  ******************************************************************************/
  42. acpi_status
  43. acpi_find_root_pointer (
  44. u32                     flags,
  45. ACPI_PHYSICAL_ADDRESS   *rsdp_physical_address)
  46. {
  47. acpi_table_desc         table_info;
  48. acpi_status             status;
  49. FUNCTION_TRACE ("Acpi_find_root_pointer");
  50. /* Get the RSDP */
  51. status = acpi_tb_find_rsdp (&table_info, flags);
  52. if (ACPI_FAILURE (status)) {
  53. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not foundn"));
  54. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  55. }
  56. *rsdp_physical_address = table_info.physical_address;
  57. return_ACPI_STATUS (AE_OK);
  58. }
  59. /*******************************************************************************
  60.  *
  61.  * FUNCTION:    Acpi_tb_scan_memory_for_rsdp
  62.  *
  63.  * PARAMETERS:  Start_address       - Starting pointer for search
  64.  *              Length              - Maximum length to search
  65.  *
  66.  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
  67.  *
  68.  * DESCRIPTION: Search a block of memory for the RSDP signature
  69.  *
  70.  ******************************************************************************/
  71. u8 *
  72. acpi_tb_scan_memory_for_rsdp (
  73. u8                      *start_address,
  74. u32                     length)
  75. {
  76. u32                     offset;
  77. u8                      *mem_rover;
  78. FUNCTION_TRACE ("Tb_scan_memory_for_rsdp");
  79. /* Search from given start addr for the requested length  */
  80. for (offset = 0, mem_rover = start_address;
  81.  offset < length;
  82.  offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) {
  83. /* The signature and checksum must both be correct */
  84. if (STRNCMP ((NATIVE_CHAR *) mem_rover,
  85. RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
  86. acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0) {
  87. /* If so, we have found the RSDP */
  88. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  89. "RSDP located at physical address %pn",mem_rover));
  90. return_PTR (mem_rover);
  91. }
  92. }
  93. /* Searched entire block, no RSDP was found */
  94. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.n"));
  95. return_PTR (NULL);
  96. }
  97. /*******************************************************************************
  98.  *
  99.  * FUNCTION:    Acpi_tb_find_rsdp
  100.  *
  101.  * PARAMETERS:  *Table_info             - Where the table info is returned
  102.  *              Flags                   - Current memory mode (logical vs.
  103.  *                                        physical addressing)
  104.  *
  105.  * RETURN:      Status
  106.  *
  107.  * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
  108.  *              pointer structure.  If it is found, set *RSDP to point to it.
  109.  *
  110.  *              NOTE: The RSDP must be either in the first 1_k of the Extended
  111.  *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
  112.  *              5.2.2; assertion #421).
  113.  *
  114.  ******************************************************************************/
  115. acpi_status
  116. acpi_tb_find_rsdp (
  117. acpi_table_desc         *table_info,
  118. u32                     flags)
  119. {
  120. u8                      *table_ptr;
  121. u8                      *mem_rover;
  122. u64                     phys_addr;
  123. acpi_status             status = AE_OK;
  124. FUNCTION_TRACE ("Tb_find_rsdp");
  125. /*
  126.  * Scan supports either 1) Logical addressing or 2) Physical addressing
  127.  */
  128. if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
  129. /*
  130.  * 1) Search EBDA (low memory) paragraphs
  131.  */
  132. status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE,
  133.   (void **) &table_ptr);
  134. if (ACPI_FAILURE (status)) {
  135. return_ACPI_STATUS (status);
  136. }
  137. mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, LO_RSDP_WINDOW_SIZE);
  138. acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE);
  139. if (mem_rover) {
  140. /* Found it, return the physical address */
  141. phys_addr = LO_RSDP_WINDOW_BASE;
  142. phys_addr += (mem_rover - table_ptr);
  143. table_info->physical_address = phys_addr;
  144. return_ACPI_STATUS (AE_OK);
  145. }
  146. /*
  147.  * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
  148.  */
  149. status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE,
  150.   (void **) &table_ptr);
  151. if (ACPI_FAILURE (status)) {
  152. return_ACPI_STATUS (status);
  153. }
  154. mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, HI_RSDP_WINDOW_SIZE);
  155. acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE);
  156. if (mem_rover) {
  157. /* Found it, return the physical address */
  158. phys_addr = HI_RSDP_WINDOW_BASE;
  159. phys_addr += (mem_rover - table_ptr);
  160. table_info->physical_address = phys_addr;
  161. return_ACPI_STATUS (AE_OK);
  162. }
  163. }
  164. /*
  165.  * Physical addressing
  166.  */
  167. else {
  168. /*
  169.  * 1) Search EBDA (low memory) paragraphs
  170.  */
  171. mem_rover = acpi_tb_scan_memory_for_rsdp ((u8 *) LO_RSDP_WINDOW_BASE,
  172.   LO_RSDP_WINDOW_SIZE);
  173. if (mem_rover) {
  174. /* Found it, return the physical address */
  175. table_info->physical_address = (ACPI_TBLPTR) mem_rover;
  176. return_ACPI_STATUS (AE_OK);
  177. }
  178. /*
  179.  * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
  180.  */
  181. mem_rover = acpi_tb_scan_memory_for_rsdp ((u8 *) HI_RSDP_WINDOW_BASE,
  182.   HI_RSDP_WINDOW_SIZE);
  183. if (mem_rover) {
  184. /* Found it, return the physical address */
  185. table_info->physical_address = (ACPI_TBLPTR) mem_rover;
  186. return_ACPI_STATUS (AE_OK);
  187. }
  188. }
  189. /* RSDP signature was not found */
  190. return_ACPI_STATUS (AE_NOT_FOUND);
  191. }
  192. /*******************************************************************************
  193.  *
  194.  * FUNCTION:    Acpi_get_firmware_table
  195.  *
  196.  * PARAMETERS:  Signature       - Any ACPI table signature
  197.  *              Instance        - the non zero instance of the table, allows
  198.  *                                support for multiple tables of the same type
  199.  *              Flags           - 0: Physical/Virtual support
  200.  *              Ret_buffer      - pointer to a structure containing a buffer to
  201.  *                                receive the table
  202.  *
  203.  * RETURN:      Status
  204.  *
  205.  * DESCRIPTION: This function is called to get an ACPI table.  The caller
  206.  *              supplies an Out_buffer large enough to contain the entire ACPI
  207.  *              table.  Upon completion
  208.  *              the Out_buffer->Length field will indicate the number of bytes
  209.  *              copied into the Out_buffer->Buf_ptr buffer. This table will be
  210.  *              a complete table including the header.
  211.  *
  212.  ******************************************************************************/
  213. acpi_status
  214. acpi_get_firmware_table (
  215. acpi_string             signature,
  216. u32                     instance,
  217. u32                     flags,
  218. acpi_table_header       **table_pointer)
  219. {
  220. ACPI_PHYSICAL_ADDRESS   physical_address;
  221. acpi_table_header       *rsdt_ptr = NULL;
  222. acpi_table_header       *table_ptr;
  223. acpi_status             status;
  224. u32                     rsdt_size = 0;
  225. u32                     table_size;
  226. u32                     table_count;
  227. u32                     i;
  228. u32                     j;
  229. FUNCTION_TRACE ("Acpi_get_firmware_table");
  230. /*
  231.  * Ensure that at least the table manager is initialized.  We don't
  232.  * require that the entire ACPI subsystem is up for this interface
  233.  */
  234. /*
  235.  *  If we have a buffer, we must have a length too
  236.  */
  237. if ((instance == 0)                 ||
  238. (!signature)                    ||
  239. (!table_pointer)) {
  240. return_ACPI_STATUS (AE_BAD_PARAMETER);
  241. }
  242. if (!acpi_gbl_RSDP) {
  243. /* Get the RSDP */
  244. status = acpi_os_get_root_pointer (flags, &physical_address);
  245. if (ACPI_FAILURE (status)) {
  246. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not foundn"));
  247. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  248. }
  249. /* Map and validate the RSDP */
  250. if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
  251. status = acpi_os_map_memory (physical_address, sizeof (RSDP_DESCRIPTOR),
  252.   (void **) &acpi_gbl_RSDP);
  253. if (ACPI_FAILURE (status)) {
  254. return_ACPI_STATUS (status);
  255. }
  256. }
  257. else {
  258. acpi_gbl_RSDP = (void *) (NATIVE_UINT) physical_address;
  259. }
  260. /*
  261.  *  The signature and checksum must both be correct
  262.  */
  263. if (STRNCMP ((NATIVE_CHAR *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
  264. /* Nope, BAD Signature */
  265. status = AE_BAD_SIGNATURE;
  266. goto cleanup;
  267. }
  268. if (acpi_tb_checksum (acpi_gbl_RSDP, RSDP_CHECKSUM_LENGTH) != 0) {
  269. /* Nope, BAD Checksum */
  270. status = AE_BAD_CHECKSUM;
  271. goto cleanup;
  272. }
  273. }
  274. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  275. "RSDP located at %p, RSDT physical=%8.8X%8.8X n",
  276. acpi_gbl_RSDP, HIDWORD(acpi_gbl_RSDP->rsdt_physical_address),
  277. LODWORD(acpi_gbl_RSDP->rsdt_physical_address)));
  278. /* Get the RSDT and validate it */
  279. physical_address = acpi_tb_get_rsdt_address ();
  280. status = acpi_tb_get_table_pointer (physical_address, flags, &rsdt_size, &rsdt_ptr);
  281. if (ACPI_FAILURE (status)) {
  282. return_ACPI_STATUS (status);
  283. }
  284. status = acpi_tb_validate_rsdt (rsdt_ptr);
  285. if (ACPI_FAILURE (status)) {
  286. goto cleanup;
  287. }
  288. /* Get the number of table pointers within the RSDT */
  289. table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_ptr);
  290. /*
  291.  * Search the RSDT/XSDT for the correct instance of the
  292.  * requested table
  293.  */
  294. for (i = 0, j = 0; i < table_count; i++) {
  295. /* Get the next table pointer */
  296. if (acpi_gbl_RSDP->revision < 2) {
  297. physical_address = ((RSDT_DESCRIPTOR *) rsdt_ptr)->table_offset_entry[i];
  298. }
  299. else {
  300. physical_address = (ACPI_PHYSICAL_ADDRESS)
  301. ACPI_GET_ADDRESS (((xsdt_descriptor *) rsdt_ptr)->table_offset_entry[i]);
  302. }
  303. /* Get addressibility if necessary */
  304. status = acpi_tb_get_table_pointer (physical_address, flags, &table_size, &table_ptr);
  305. if (ACPI_FAILURE (status)) {
  306. goto cleanup;
  307. }
  308. /* Compare table signatures and table instance */
  309. if (!STRNCMP ((char *) table_ptr, signature, STRLEN (signature))) {
  310. /* An instance of the table was found */
  311. j++;
  312. if (j >= instance) {
  313. /* Found the correct instance */
  314. *table_pointer = table_ptr;
  315. goto cleanup;
  316. }
  317. }
  318. /* Delete table mapping if using virtual addressing */
  319. if ((table_size) &&
  320. ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING)) {
  321. acpi_os_unmap_memory (table_ptr, table_size);
  322. }
  323. }
  324. /* Did not find the table */
  325. status = AE_NOT_EXIST;
  326. cleanup:
  327. if (rsdt_size) {
  328. acpi_os_unmap_memory (rsdt_ptr, rsdt_size);
  329. }
  330. return_ACPI_STATUS (status);
  331. }