Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentbget.c
Go to the documentation of this file.
00001 /****************************************************************************** 00002 * 00003 * Module Name: tbget - ACPI Table get* routines 00004 * $Revision: 1.1 $ 00005 * 00006 *****************************************************************************/ 00007 00008 /* 00009 * Copyright (C) 2000, 2001 R. Byron Moore 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 */ 00025 00026 00027 #include <acpi.h> 00028 00029 #define _COMPONENT ACPI_TABLES 00030 MODULE_NAME ("tbget") 00031 00032 #define RSDP_CHECKSUM_LENGTH 20 00033 00034 /******************************************************************************* 00035 * 00036 * FUNCTION: Acpi_tb_get_table_ptr 00037 * 00038 * PARAMETERS: Table_type - one of the defined table types 00039 * Instance - Which table of this type 00040 * Table_ptr_loc - pointer to location to place the pointer for 00041 * return 00042 * 00043 * RETURN: Status 00044 * 00045 * DESCRIPTION: This function is called to get the pointer to an ACPI table. 00046 * 00047 ******************************************************************************/ 00048 00049 ACPI_STATUS 00050 acpi_tb_get_table_ptr ( 00051 ACPI_TABLE_TYPE table_type, 00052 u32 instance, 00053 ACPI_TABLE_HEADER **table_ptr_loc) 00054 { 00055 ACPI_TABLE_DESC *table_desc; 00056 u32 i; 00057 00058 00059 if (!acpi_gbl_DSDT) { 00060 return (AE_NO_ACPI_TABLES); 00061 } 00062 00063 if (table_type > ACPI_TABLE_MAX) { 00064 return (AE_BAD_PARAMETER); 00065 } 00066 00067 00068 /* 00069 * For all table types (Single/Multiple), the first 00070 * instance is always in the list head. 00071 */ 00072 00073 if (instance == 1) { 00074 /* 00075 * Just pluck the pointer out of the global table! 00076 * Will be null if no table is present 00077 */ 00078 00079 *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; 00080 return (AE_OK); 00081 } 00082 00083 00084 /* 00085 * Check for instance out of range 00086 */ 00087 if (instance > acpi_gbl_acpi_tables[table_type].count) { 00088 return (AE_NOT_EXIST); 00089 } 00090 00091 /* Walk the list to get the desired table 00092 * Since the if (Instance == 1) check above checked for the 00093 * first table, setting Table_desc equal to the .Next member 00094 * is actually pointing to the second table. Therefore, we 00095 * need to walk from the 2nd table until we reach the Instance 00096 * that the user is looking for and return its table pointer. 00097 */ 00098 table_desc = acpi_gbl_acpi_tables[table_type].next; 00099 for (i = 2; i < instance; i++) { 00100 table_desc = table_desc->next; 00101 } 00102 00103 /* We are now pointing to the requested table's descriptor */ 00104 00105 *table_ptr_loc = table_desc->pointer; 00106 00107 return (AE_OK); 00108 } 00109 00110 00111 /******************************************************************************* 00112 * 00113 * FUNCTION: Acpi_tb_get_table 00114 * 00115 * PARAMETERS: Physical_address - Physical address of table to retrieve 00116 * *Buffer_ptr - If Buffer_ptr is valid, read data from 00117 * buffer rather than searching memory 00118 * *Table_info - Where the table info is returned 00119 * 00120 * RETURN: Status 00121 * 00122 * DESCRIPTION: Maps the physical address of table into a logical address 00123 * 00124 ******************************************************************************/ 00125 00126 ACPI_STATUS 00127 acpi_tb_get_table ( 00128 ACPI_PHYSICAL_ADDRESS physical_address, 00129 ACPI_TABLE_HEADER *buffer_ptr, 00130 ACPI_TABLE_DESC *table_info) 00131 { 00132 ACPI_TABLE_HEADER *table_header = NULL; 00133 ACPI_TABLE_HEADER *full_table = NULL; 00134 u32 size; 00135 u8 allocation; 00136 ACPI_STATUS status = AE_OK; 00137 00138 00139 if (!table_info) { 00140 return (AE_BAD_PARAMETER); 00141 } 00142 00143 00144 if (buffer_ptr) { 00145 /* 00146 * Getting data from a buffer, not BIOS tables 00147 */ 00148 00149 table_header = buffer_ptr; 00150 status = acpi_tb_validate_table_header (table_header); 00151 if (ACPI_FAILURE (status)) { 00152 /* Table failed verification, map all errors to BAD_DATA */ 00153 00154 return (AE_BAD_DATA); 00155 } 00156 00157 /* Allocate buffer for the entire table */ 00158 00159 full_table = acpi_cm_allocate (table_header->length); 00160 if (!full_table) { 00161 return (AE_NO_MEMORY); 00162 } 00163 00164 /* Copy the entire table (including header) to the local buffer */ 00165 00166 size = table_header->length; 00167 MEMCPY (full_table, buffer_ptr, size); 00168 00169 /* Save allocation type */ 00170 00171 allocation = ACPI_MEM_ALLOCATED; 00172 } 00173 00174 00175 /* 00176 * Not reading from a buffer, just map the table's physical memory 00177 * into our address space. 00178 */ 00179 else { 00180 size = SIZE_IN_HEADER; 00181 00182 status = acpi_tb_map_acpi_table (physical_address, &size, 00183 (void **) &full_table); 00184 if (ACPI_FAILURE (status)) { 00185 return (status); 00186 } 00187 00188 /* Save allocation type */ 00189 00190 allocation = ACPI_MEM_MAPPED; 00191 } 00192 00193 00194 /* Return values */ 00195 00196 table_info->pointer = full_table; 00197 table_info->length = size; 00198 table_info->allocation = allocation; 00199 table_info->base_pointer = full_table; 00200 00201 return (status); 00202 } 00203 00204 00205 /******************************************************************************* 00206 * 00207 * FUNCTION: Acpi_tb_get_all_tables 00208 * 00209 * PARAMETERS: Number_of_tables - Number of tables to get 00210 * Table_ptr - Input buffer pointer, optional 00211 * 00212 * RETURN: Status 00213 * 00214 * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must 00215 * already be loaded and validated. 00216 * 00217 ******************************************************************************/ 00218 00219 ACPI_STATUS 00220 acpi_tb_get_all_tables ( 00221 u32 number_of_tables, 00222 ACPI_TABLE_HEADER *table_ptr) 00223 { 00224 ACPI_STATUS status = AE_OK; 00225 u32 index; 00226 ACPI_TABLE_DESC table_info; 00227 00228 00229 /* 00230 * Loop through all table pointers found in RSDT. 00231 * This will NOT include the FACS and DSDT - we must get 00232 * them after the loop 00233 */ 00234 00235 for (index = 0; index < number_of_tables; index++) { 00236 /* Clear the Table_info each time */ 00237 00238 MEMSET (&table_info, 0, sizeof (ACPI_TABLE_DESC)); 00239 00240 /* Get the table via the XSDT */ 00241 00242 status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) 00243 ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]), 00244 table_ptr, &table_info); 00245 00246 /* Ignore a table that failed verification */ 00247 00248 if (status == AE_BAD_DATA) { 00249 continue; 00250 } 00251 00252 /* However, abort on serious errors */ 00253 00254 if (ACPI_FAILURE (status)) { 00255 return (status); 00256 } 00257 00258 /* Recognize and install the table */ 00259 00260 status = acpi_tb_install_table (table_ptr, &table_info); 00261 if (ACPI_FAILURE (status)) { 00262 /* 00263 * Unrecognized or unsupported table, delete it and ignore the 00264 * error. Just get as many tables as we can, later we will 00265 * determine if there are enough tables to continue. 00266 */ 00267 00268 acpi_tb_uninstall_table (&table_info); 00269 } 00270 } 00271 00272 00273 /* 00274 * Convert the FADT to a common format. This allows earlier revisions of the 00275 * table to coexist with newer versions, using common access code. 00276 */ 00277 status = acpi_tb_convert_table_fadt (); 00278 if (ACPI_FAILURE (status)) { 00279 return (status); 00280 } 00281 00282 00283 /* 00284 * Get the minimum set of ACPI tables, namely: 00285 * 00286 * 1) FADT (via RSDT in loop above) 00287 * 2) FACS 00288 * 3) DSDT 00289 * 00290 */ 00291 00292 00293 /* 00294 * Get the FACS (must have the FADT first, from loop above) 00295 * Acpi_tb_get_table_facs will fail if FADT pointer is not valid 00296 */ 00297 00298 status = acpi_tb_get_table_facs (table_ptr, &table_info); 00299 if (ACPI_FAILURE (status)) { 00300 return (status); 00301 } 00302 00303 00304 /* Install the FACS */ 00305 00306 status = acpi_tb_install_table (table_ptr, &table_info); 00307 if (ACPI_FAILURE (status)) { 00308 return (status); 00309 } 00310 00311 /* 00312 * Create the common FACS pointer table 00313 * (Contains pointers to the original table) 00314 */ 00315 00316 status = acpi_tb_build_common_facs (&table_info); 00317 if (ACPI_FAILURE (status)) { 00318 return (status); 00319 } 00320 00321 00322 /* 00323 * Get the DSDT (We know that the FADT is valid now) 00324 */ 00325 00326 status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt), 00327 table_ptr, &table_info); 00328 if (ACPI_FAILURE (status)) { 00329 return (status); 00330 } 00331 00332 /* Install the DSDT */ 00333 00334 status = acpi_tb_install_table (table_ptr, &table_info); 00335 if (ACPI_FAILURE (status)) { 00336 return (status); 00337 } 00338 00339 /* Dump the DSDT Header */ 00340 00341 /* Dump the entire DSDT */ 00342 00343 /* 00344 * Initialize the capabilities flags. 00345 * Assumes that platform supports ACPI_MODE since we have tables! 00346 */ 00347 acpi_gbl_system_flags |= acpi_hw_get_mode_capabilities (); 00348 00349 00350 /* Always delete the RSDP mapping, we are done with it */ 00351 00352 acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP); 00353 00354 return (status); 00355 } 00356 00357 00358 /******************************************************************************* 00359 * 00360 * FUNCTION: Acpi_tb_verify_rsdp 00361 * 00362 * PARAMETERS: Number_of_tables - Where the table count is placed 00363 * 00364 * RETURN: Status 00365 * 00366 * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) 00367 * 00368 ******************************************************************************/ 00369 00370 ACPI_STATUS 00371 acpi_tb_verify_rsdp ( 00372 ACPI_PHYSICAL_ADDRESS rsdp_physical_address) 00373 { 00374 ACPI_TABLE_DESC table_info; 00375 ACPI_STATUS status; 00376 u8 *table_ptr; 00377 00378 00379 /* 00380 * Obtain access to the RSDP structure 00381 */ 00382 status = acpi_os_map_memory (rsdp_physical_address, 00383 sizeof (RSDP_DESCRIPTOR), 00384 (void **) &table_ptr); 00385 if (ACPI_FAILURE (status)) { 00386 return (status); 00387 } 00388 00389 /* 00390 * The signature and checksum must both be correct 00391 */ 00392 if (STRNCMP ((NATIVE_CHAR *) table_ptr, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { 00393 /* Nope, BAD Signature */ 00394 00395 status = AE_BAD_SIGNATURE; 00396 goto cleanup; 00397 } 00398 00399 if (acpi_tb_checksum (table_ptr, RSDP_CHECKSUM_LENGTH) != 0) { 00400 /* Nope, BAD Checksum */ 00401 00402 status = AE_BAD_CHECKSUM; 00403 goto cleanup; 00404 } 00405 00406 /* TBD: Check extended checksum if table version >= 2 */ 00407 00408 /* The RSDP supplied is OK */ 00409 00410 table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; 00411 table_info.length = sizeof (RSDP_DESCRIPTOR); 00412 table_info.allocation = ACPI_MEM_MAPPED; 00413 table_info.base_pointer = table_ptr; 00414 00415 /* Save the table pointers and allocation info */ 00416 00417 status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info); 00418 if (ACPI_FAILURE (status)) { 00419 goto cleanup; 00420 } 00421 00422 00423 /* Save the RSDP in a global for easy access */ 00424 00425 acpi_gbl_RSDP = (RSDP_DESCRIPTOR *) table_info.pointer; 00426 return (status); 00427 00428 00429 /* Error exit */ 00430 cleanup: 00431 00432 acpi_os_unmap_memory (table_ptr, sizeof (RSDP_DESCRIPTOR)); 00433 return (status); 00434 } 00435 00436 00437 /******************************************************************************* 00438 * 00439 * FUNCTION: Acpi_tb_get_table_rsdt 00440 * 00441 * PARAMETERS: Number_of_tables - Where the table count is placed 00442 * 00443 * RETURN: Status 00444 * 00445 * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) 00446 * 00447 ******************************************************************************/ 00448 00449 ACPI_STATUS 00450 acpi_tb_get_table_rsdt ( 00451 u32 *number_of_tables) 00452 { 00453 ACPI_TABLE_DESC table_info; 00454 ACPI_STATUS status = AE_OK; 00455 ACPI_PHYSICAL_ADDRESS physical_address; 00456 u32 signature_length; 00457 char *table_signature; 00458 00459 00460 /* 00461 * Get the RSDT from the RSDP 00462 */ 00463 00464 /* 00465 * For RSDP revision 0 or 1, we use the RSDT. 00466 * For RSDP revision 2 (and above), we use the XSDT 00467 */ 00468 if (acpi_gbl_RSDP->revision < 2) { 00469 #ifdef _IA64 00470 /* 0.71 RSDP has 64bit Rsdt address field */ 00471 physical_address = ((RSDP_DESCRIPTOR_REV071 *)acpi_gbl_RSDP)->rsdt_physical_address; 00472 #else 00473 physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address; 00474 #endif 00475 table_signature = RSDT_SIG; 00476 signature_length = sizeof (RSDT_SIG) -1; 00477 } 00478 else { 00479 physical_address = (ACPI_PHYSICAL_ADDRESS) 00480 ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address); 00481 table_signature = XSDT_SIG; 00482 signature_length = sizeof (XSDT_SIG) -1; 00483 } 00484 00485 00486 /* Get the RSDT/XSDT */ 00487 00488 status = acpi_tb_get_table (physical_address, NULL, &table_info); 00489 if (ACPI_FAILURE (status)) { 00490 return (status); 00491 } 00492 00493 00494 /* Check the RSDT or XSDT signature */ 00495 00496 if (STRNCMP ((char *) table_info.pointer, table_signature, 00497 signature_length)) { 00498 /* Invalid RSDT or XSDT signature */ 00499 00500 REPORT_ERROR (("Invalid signature where RSDP indicates %s should be located\n", 00501 table_signature)); 00502 00503 return (AE_NO_ACPI_TABLES); 00504 } 00505 00506 00507 /* Valid RSDT signature, verify the checksum */ 00508 00509 status = acpi_tb_verify_table_checksum (table_info.pointer); 00510 00511 00512 /* Convert and/or copy to an XSDT structure */ 00513 00514 status = acpi_tb_convert_to_xsdt (&table_info, number_of_tables); 00515 if (ACPI_FAILURE (status)) { 00516 return (status); 00517 } 00518 00519 /* Save the table pointers and allocation info */ 00520 00521 status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info); 00522 if (ACPI_FAILURE (status)) { 00523 return (status); 00524 } 00525 00526 acpi_gbl_XSDT = (XSDT_DESCRIPTOR *) table_info.pointer; 00527 00528 return (status); 00529 } 00530 00531 00532 /****************************************************************************** 00533 * 00534 * FUNCTION: Acpi_tb_get_table_facs 00535 * 00536 * PARAMETERS: *Buffer_ptr - If Buffer_ptr is valid, read data from 00537 * buffer rather than searching memory 00538 * *Table_info - Where the table info is returned 00539 * 00540 * RETURN: Status 00541 * 00542 * DESCRIPTION: Returns a pointer to the FACS as defined in FADT. This 00543 * function assumes the global variable FADT has been 00544 * correctly initialized. The value of FADT->Firmware_ctrl 00545 * into a far pointer which is returned. 00546 * 00547 *****************************************************************************/ 00548 00549 ACPI_STATUS 00550 acpi_tb_get_table_facs ( 00551 ACPI_TABLE_HEADER *buffer_ptr, 00552 ACPI_TABLE_DESC *table_info) 00553 { 00554 void *table_ptr = NULL; 00555 u32 size; 00556 u8 allocation; 00557 ACPI_STATUS status = AE_OK; 00558 00559 00560 /* Must have a valid FADT pointer */ 00561 00562 if (!acpi_gbl_FADT) { 00563 return (AE_NO_ACPI_TABLES); 00564 } 00565 00566 size = sizeof (FACS_DESCRIPTOR); 00567 if (buffer_ptr) { 00568 /* 00569 * Getting table from a file -- allocate a buffer and 00570 * read the table. 00571 */ 00572 table_ptr = acpi_cm_allocate (size); 00573 if(!table_ptr) { 00574 return (AE_NO_MEMORY); 00575 } 00576 00577 MEMCPY (table_ptr, buffer_ptr, size); 00578 00579 /* Save allocation type */ 00580 00581 allocation = ACPI_MEM_ALLOCATED; 00582 } 00583 00584 else { 00585 /* Just map the physical memory to our address space */ 00586 00587 status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl), 00588 &size, &table_ptr); 00589 if (ACPI_FAILURE(status)) { 00590 return (status); 00591 } 00592 00593 /* Save allocation type */ 00594 00595 allocation = ACPI_MEM_MAPPED; 00596 } 00597 00598 00599 /* Return values */ 00600 00601 table_info->pointer = table_ptr; 00602 table_info->length = size; 00603 table_info->allocation = allocation; 00604 table_info->base_pointer = table_ptr; 00605 00606 return (status); 00607 } 00608 Generated on Sat May 26 2012 04:25:56 for ReactOS by
1.7.6.1
|