| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /****************************************************************************** | 
|  | 2 | * | 
|  | 3 | * Module Name: tbinstal - ACPI table installation and removal | 
|  | 4 | * | 
|  | 5 | *****************************************************************************/ | 
|  | 6 |  | 
|  | 7 | /* | 
| Bob Moore | 4a90c7e | 2006-01-13 16:22:00 -0500 | [diff] [blame] | 8 | * Copyright (C) 2000 - 2006, R. Byron Moore | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9 | * All rights reserved. | 
|  | 10 | * | 
|  | 11 | * Redistribution and use in source and binary forms, with or without | 
|  | 12 | * modification, are permitted provided that the following conditions | 
|  | 13 | * are met: | 
|  | 14 | * 1. Redistributions of source code must retain the above copyright | 
|  | 15 | *    notice, this list of conditions, and the following disclaimer, | 
|  | 16 | *    without modification. | 
|  | 17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | 
|  | 18 | *    substantially similar to the "NO WARRANTY" disclaimer below | 
|  | 19 | *    ("Disclaimer") and any redistribution must be conditioned upon | 
|  | 20 | *    including a substantially similar Disclaimer requirement for further | 
|  | 21 | *    binary redistribution. | 
|  | 22 | * 3. Neither the names of the above-listed copyright holders nor the names | 
|  | 23 | *    of any contributors may be used to endorse or promote products derived | 
|  | 24 | *    from this software without specific prior written permission. | 
|  | 25 | * | 
|  | 26 | * Alternatively, this software may be distributed under the terms of the | 
|  | 27 | * GNU General Public License ("GPL") version 2 as published by the Free | 
|  | 28 | * Software Foundation. | 
|  | 29 | * | 
|  | 30 | * NO WARRANTY | 
|  | 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | 32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | 33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | 
|  | 34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | 35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
|  | 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
|  | 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
|  | 39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | 
|  | 40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|  | 41 | * POSSIBILITY OF SUCH DAMAGES. | 
|  | 42 | */ | 
|  | 43 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | #include <acpi/acpi.h> | 
|  | 45 | #include <acpi/actables.h> | 
|  | 46 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | #define _COMPONENT          ACPI_TABLES | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 48 | ACPI_MODULE_NAME("tbinstal") | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 50 | /* Local prototypes */ | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 51 | static acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 52 | acpi_tb_match_signature(char *signature, | 
|  | 53 | struct acpi_table_desc *table_info, u8 search_type); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 |  | 
|  | 55 | /******************************************************************************* | 
|  | 56 | * | 
|  | 57 | * FUNCTION:    acpi_tb_match_signature | 
|  | 58 | * | 
|  | 59 | * PARAMETERS:  Signature           - Table signature to match | 
|  | 60 | *              table_info          - Return data | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 61 | *              search_type         - Table type to match (primary/secondary) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 62 | * | 
|  | 63 | * RETURN:      Status | 
|  | 64 | * | 
|  | 65 | * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" | 
|  | 66 | *              tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. | 
|  | 67 | * | 
|  | 68 | ******************************************************************************/ | 
|  | 69 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 70 | static acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 71 | acpi_tb_match_signature(char *signature, | 
|  | 72 | struct acpi_table_desc *table_info, u8 search_type) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 73 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 74 | acpi_native_uint i; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 76 | ACPI_FUNCTION_TRACE("tb_match_signature"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 77 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 78 | /* Search for a signature match among the known table types */ | 
|  | 79 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 | for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { | 
|  | 81 | if (!(acpi_gbl_table_data[i].flags & search_type)) { | 
|  | 82 | continue; | 
|  | 83 | } | 
|  | 84 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 85 | if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, | 
|  | 86 | acpi_gbl_table_data[i].sig_length)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | /* Found a signature match, return index if requested */ | 
|  | 88 |  | 
|  | 89 | if (table_info) { | 
|  | 90 | table_info->type = (u8) i; | 
|  | 91 | } | 
|  | 92 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 93 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 
|  | 94 | "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", | 
|  | 95 | (char *)acpi_gbl_table_data[i]. | 
|  | 96 | signature)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 97 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 98 | return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 99 | } | 
|  | 100 | } | 
|  | 101 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 102 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 
|  | 103 | "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", | 
|  | 104 | (char *)signature)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 106 | return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 | } | 
|  | 108 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 | /******************************************************************************* | 
|  | 110 | * | 
|  | 111 | * FUNCTION:    acpi_tb_install_table | 
|  | 112 | * | 
|  | 113 | * PARAMETERS:  table_info          - Return value from acpi_tb_get_table_body | 
|  | 114 | * | 
|  | 115 | * RETURN:      Status | 
|  | 116 | * | 
| Robert Moore | 0c9938c | 2005-07-29 15:15:00 -0700 | [diff] [blame] | 117 | * DESCRIPTION: Install the table into the global data structures. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 118 | * | 
|  | 119 | ******************************************************************************/ | 
|  | 120 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 121 | acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 123 | acpi_status status; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 124 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 125 | ACPI_FUNCTION_TRACE("tb_install_table"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 126 |  | 
|  | 127 | /* Lock tables while installing */ | 
|  | 128 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 129 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 
|  | 130 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 131 | ACPI_EXCEPTION((AE_INFO, status, | 
|  | 132 | "Could not acquire table mutex")); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 133 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 134 | } | 
|  | 135 |  | 
| Robert Moore | 0c9938c | 2005-07-29 15:15:00 -0700 | [diff] [blame] | 136 | /* | 
|  | 137 | * Ignore a table that is already installed. For example, some BIOS | 
|  | 138 | * ASL code will repeatedly attempt to load the same SSDT. | 
|  | 139 | */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 140 | status = acpi_tb_is_table_installed(table_info); | 
|  | 141 | if (ACPI_FAILURE(status)) { | 
| Robert Moore | 0c9938c | 2005-07-29 15:15:00 -0700 | [diff] [blame] | 142 | goto unlock_and_exit; | 
|  | 143 | } | 
|  | 144 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | /* Install the table into the global data structure */ | 
|  | 146 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 147 | status = acpi_tb_init_table_descriptor(table_info->type, table_info); | 
|  | 148 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 149 | ACPI_EXCEPTION((AE_INFO, status, | 
|  | 150 | "Could not install table [%4.4s]", | 
|  | 151 | table_info->pointer->signature)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 152 | } | 
|  | 153 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 154 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", | 
|  | 155 | acpi_gbl_table_data[table_info->type].name, | 
|  | 156 | table_info->pointer)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 158 | unlock_and_exit: | 
|  | 159 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 
|  | 160 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 161 | } | 
|  | 162 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 163 | /******************************************************************************* | 
|  | 164 | * | 
|  | 165 | * FUNCTION:    acpi_tb_recognize_table | 
|  | 166 | * | 
|  | 167 | * PARAMETERS:  table_info          - Return value from acpi_tb_get_table_body | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 168 | *              search_type         - Table type to match (primary/secondary) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 169 | * | 
|  | 170 | * RETURN:      Status | 
|  | 171 | * | 
|  | 172 | * DESCRIPTION: Check a table signature for a match against known table types | 
|  | 173 | * | 
|  | 174 | * NOTE:  All table pointers are validated as follows: | 
|  | 175 | *          1) Table pointer must point to valid physical memory | 
|  | 176 | *          2) Signature must be 4 ASCII chars, even if we don't recognize the | 
|  | 177 | *             name | 
|  | 178 | *          3) Table must be readable for length specified in the header | 
|  | 179 | *          4) Table checksum must be valid (with the exception of the FACS | 
|  | 180 | *             which has no checksum for some odd reason) | 
|  | 181 | * | 
|  | 182 | ******************************************************************************/ | 
|  | 183 |  | 
|  | 184 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 185 | acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 186 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 187 | struct acpi_table_header *table_header; | 
|  | 188 | acpi_status status; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 189 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 190 | ACPI_FUNCTION_TRACE("tb_recognize_table"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 191 |  | 
|  | 192 | /* Ensure that we have a valid table pointer */ | 
|  | 193 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 194 | table_header = (struct acpi_table_header *)table_info->pointer; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 | if (!table_header) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 196 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 | } | 
|  | 198 |  | 
|  | 199 | /* | 
|  | 200 | * We only "recognize" a limited number of ACPI tables -- namely, the | 
|  | 201 | * ones that are used by the subsystem (DSDT, FADT, etc.) | 
|  | 202 | * | 
|  | 203 | * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. | 
|  | 204 | * This can be any one of many valid ACPI tables, it just isn't one of | 
|  | 205 | * the tables that is consumed by the core subsystem | 
|  | 206 | */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 207 | status = acpi_tb_match_signature(table_header->signature, | 
|  | 208 | table_info, search_type); | 
|  | 209 | if (ACPI_FAILURE(status)) { | 
|  | 210 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 211 | } | 
|  | 212 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 213 | status = acpi_tb_validate_table_header(table_header); | 
|  | 214 | if (ACPI_FAILURE(status)) { | 
|  | 215 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 216 | } | 
|  | 217 |  | 
|  | 218 | /* Return the table type and length via the info struct */ | 
|  | 219 |  | 
|  | 220 | table_info->length = (acpi_size) table_header->length; | 
|  | 221 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 222 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 225 | /******************************************************************************* | 
|  | 226 | * | 
|  | 227 | * FUNCTION:    acpi_tb_init_table_descriptor | 
|  | 228 | * | 
|  | 229 | * PARAMETERS:  table_type          - The type of the table | 
|  | 230 | *              table_info          - A table info struct | 
|  | 231 | * | 
|  | 232 | * RETURN:      None. | 
|  | 233 | * | 
|  | 234 | * DESCRIPTION: Install a table into the global data structs. | 
|  | 235 | * | 
|  | 236 | ******************************************************************************/ | 
|  | 237 |  | 
|  | 238 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 239 | acpi_tb_init_table_descriptor(acpi_table_type table_type, | 
|  | 240 | struct acpi_table_desc *table_info) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 241 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 242 | struct acpi_table_list *list_head; | 
|  | 243 | struct acpi_table_desc *table_desc; | 
|  | 244 | acpi_status status; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 245 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 246 | ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 247 |  | 
|  | 248 | /* Allocate a descriptor for this table */ | 
|  | 249 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 250 | table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 251 | if (!table_desc) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 252 | return_ACPI_STATUS(AE_NO_MEMORY); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 253 | } | 
|  | 254 |  | 
| Robert Moore | f9f4601 | 2005-07-08 00:00:00 -0400 | [diff] [blame] | 255 | /* Get a new owner ID for the table */ | 
|  | 256 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 257 | status = acpi_ut_allocate_owner_id(&table_desc->owner_id); | 
|  | 258 | if (ACPI_FAILURE(status)) { | 
|  | 259 | return_ACPI_STATUS(status); | 
| Robert Moore | f9f4601 | 2005-07-08 00:00:00 -0400 | [diff] [blame] | 260 | } | 
|  | 261 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 262 | /* Install the table into the global data structure */ | 
|  | 263 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | list_head = &acpi_gbl_table_lists[table_type]; | 
|  | 265 |  | 
|  | 266 | /* | 
|  | 267 | * Two major types of tables:  1) Only one instance is allowed.  This | 
|  | 268 | * includes most ACPI tables such as the DSDT.  2) Multiple instances of | 
|  | 269 | * the table are allowed.  This includes SSDT and PSDTs. | 
|  | 270 | */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 271 | if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 272 | /* | 
|  | 273 | * Only one table allowed, and a table has alread been installed | 
|  | 274 | * at this location, so return an error. | 
|  | 275 | */ | 
|  | 276 | if (list_head->next) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 277 | ACPI_MEM_FREE(table_desc); | 
|  | 278 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 279 | } | 
|  | 280 |  | 
|  | 281 | table_desc->next = list_head->next; | 
|  | 282 | list_head->next = table_desc; | 
|  | 283 |  | 
|  | 284 | if (table_desc->next) { | 
|  | 285 | table_desc->next->prev = table_desc; | 
|  | 286 | } | 
|  | 287 |  | 
|  | 288 | list_head->count++; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 289 | } else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 290 | /* | 
|  | 291 | * Link the new table in to the list of tables of this type. | 
|  | 292 | * Insert at the end of the list, order IS IMPORTANT. | 
|  | 293 | * | 
|  | 294 | * table_desc->Prev & Next are already NULL from calloc() | 
|  | 295 | */ | 
|  | 296 | list_head->count++; | 
|  | 297 |  | 
|  | 298 | if (!list_head->next) { | 
|  | 299 | list_head->next = table_desc; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 300 | } else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 301 | table_desc->next = list_head->next; | 
|  | 302 |  | 
|  | 303 | while (table_desc->next->next) { | 
|  | 304 | table_desc->next = table_desc->next->next; | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | table_desc->next->next = table_desc; | 
|  | 308 | table_desc->prev = table_desc->next; | 
|  | 309 | table_desc->next = NULL; | 
|  | 310 | } | 
|  | 311 | } | 
|  | 312 |  | 
|  | 313 | /* Finish initialization of the table descriptor */ | 
|  | 314 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 315 | table_desc->type = (u8) table_type; | 
|  | 316 | table_desc->pointer = table_info->pointer; | 
|  | 317 | table_desc->length = table_info->length; | 
|  | 318 | table_desc->allocation = table_info->allocation; | 
|  | 319 | table_desc->aml_start = (u8 *) (table_desc->pointer + 1), | 
|  | 320 | table_desc->aml_length = (u32) (table_desc->length - | 
|  | 321 | (u32) sizeof(struct | 
|  | 322 | acpi_table_header)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 323 | table_desc->loaded_into_namespace = FALSE; | 
|  | 324 |  | 
|  | 325 | /* | 
|  | 326 | * Set the appropriate global pointer (if there is one) to point to the | 
|  | 327 | * newly installed table | 
|  | 328 | */ | 
|  | 329 | if (acpi_gbl_table_data[table_type].global_ptr) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 330 | *(acpi_gbl_table_data[table_type].global_ptr) = | 
|  | 331 | table_info->pointer; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 332 | } | 
|  | 333 |  | 
|  | 334 | /* Return Data */ | 
|  | 335 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 336 | table_info->owner_id = table_desc->owner_id; | 
|  | 337 | table_info->installed_desc = table_desc; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 338 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 339 | return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 340 | } | 
|  | 341 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 342 | /******************************************************************************* | 
|  | 343 | * | 
|  | 344 | * FUNCTION:    acpi_tb_delete_all_tables | 
|  | 345 | * | 
|  | 346 | * PARAMETERS:  None. | 
|  | 347 | * | 
|  | 348 | * RETURN:      None. | 
|  | 349 | * | 
|  | 350 | * DESCRIPTION: Delete all internal ACPI tables | 
|  | 351 | * | 
|  | 352 | ******************************************************************************/ | 
|  | 353 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 354 | void acpi_tb_delete_all_tables(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 355 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 356 | acpi_table_type type; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 357 |  | 
|  | 358 | /* | 
|  | 359 | * Free memory allocated for ACPI tables | 
|  | 360 | * Memory can either be mapped or allocated | 
|  | 361 | */ | 
|  | 362 | for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 363 | acpi_tb_delete_tables_by_type(type); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 364 | } | 
|  | 365 | } | 
|  | 366 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 367 | /******************************************************************************* | 
|  | 368 | * | 
|  | 369 | * FUNCTION:    acpi_tb_delete_tables_by_type | 
|  | 370 | * | 
|  | 371 | * PARAMETERS:  Type                - The table type to be deleted | 
|  | 372 | * | 
|  | 373 | * RETURN:      None. | 
|  | 374 | * | 
|  | 375 | * DESCRIPTION: Delete an internal ACPI table | 
|  | 376 | *              Locks the ACPI table mutex | 
|  | 377 | * | 
|  | 378 | ******************************************************************************/ | 
|  | 379 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 380 | void acpi_tb_delete_tables_by_type(acpi_table_type type) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 381 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 382 | struct acpi_table_desc *table_desc; | 
|  | 383 | u32 count; | 
|  | 384 | u32 i; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 385 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 386 | ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 387 |  | 
|  | 388 | if (type > ACPI_TABLE_MAX) { | 
|  | 389 | return_VOID; | 
|  | 390 | } | 
|  | 391 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 392 | if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 393 | return; | 
|  | 394 | } | 
|  | 395 |  | 
|  | 396 | /* Clear the appropriate "typed" global table pointer */ | 
|  | 397 |  | 
|  | 398 | switch (type) { | 
|  | 399 | case ACPI_TABLE_RSDP: | 
|  | 400 | acpi_gbl_RSDP = NULL; | 
|  | 401 | break; | 
|  | 402 |  | 
|  | 403 | case ACPI_TABLE_DSDT: | 
|  | 404 | acpi_gbl_DSDT = NULL; | 
|  | 405 | break; | 
|  | 406 |  | 
|  | 407 | case ACPI_TABLE_FADT: | 
|  | 408 | acpi_gbl_FADT = NULL; | 
|  | 409 | break; | 
|  | 410 |  | 
|  | 411 | case ACPI_TABLE_FACS: | 
|  | 412 | acpi_gbl_FACS = NULL; | 
|  | 413 | break; | 
|  | 414 |  | 
|  | 415 | case ACPI_TABLE_XSDT: | 
|  | 416 | acpi_gbl_XSDT = NULL; | 
|  | 417 | break; | 
|  | 418 |  | 
|  | 419 | case ACPI_TABLE_SSDT: | 
|  | 420 | case ACPI_TABLE_PSDT: | 
|  | 421 | default: | 
|  | 422 | break; | 
|  | 423 | } | 
|  | 424 |  | 
|  | 425 | /* | 
|  | 426 | * Free the table | 
|  | 427 | * 1) Get the head of the list | 
|  | 428 | */ | 
|  | 429 | table_desc = acpi_gbl_table_lists[type].next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 430 | count = acpi_gbl_table_lists[type].count; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 431 |  | 
|  | 432 | /* | 
|  | 433 | * 2) Walk the entire list, deleting both the allocated tables | 
|  | 434 | *    and the table descriptors | 
|  | 435 | */ | 
|  | 436 | for (i = 0; i < count; i++) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 437 | table_desc = acpi_tb_uninstall_table(table_desc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 438 | } | 
|  | 439 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 440 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 441 | return_VOID; | 
|  | 442 | } | 
|  | 443 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 444 | /******************************************************************************* | 
|  | 445 | * | 
|  | 446 | * FUNCTION:    acpi_tb_delete_single_table | 
|  | 447 | * | 
|  | 448 | * PARAMETERS:  table_info          - A table info struct | 
|  | 449 | * | 
|  | 450 | * RETURN:      None. | 
|  | 451 | * | 
|  | 452 | * DESCRIPTION: Low-level free for a single ACPI table.  Handles cases where | 
|  | 453 | *              the table was allocated a buffer or was mapped. | 
|  | 454 | * | 
|  | 455 | ******************************************************************************/ | 
|  | 456 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 457 | void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 458 | { | 
|  | 459 |  | 
|  | 460 | /* Must have a valid table descriptor and pointer */ | 
|  | 461 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 462 | if ((!table_desc) || (!table_desc->pointer)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 463 | return; | 
|  | 464 | } | 
|  | 465 |  | 
|  | 466 | /* Valid table, determine type of memory allocation */ | 
|  | 467 |  | 
|  | 468 | switch (table_desc->allocation) { | 
|  | 469 | case ACPI_MEM_NOT_ALLOCATED: | 
|  | 470 | break; | 
|  | 471 |  | 
|  | 472 | case ACPI_MEM_ALLOCATED: | 
|  | 473 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 474 | ACPI_MEM_FREE(table_desc->pointer); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 475 | break; | 
|  | 476 |  | 
|  | 477 | case ACPI_MEM_MAPPED: | 
|  | 478 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 479 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 480 | break; | 
|  | 481 |  | 
|  | 482 | default: | 
|  | 483 | break; | 
|  | 484 | } | 
|  | 485 | } | 
|  | 486 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 487 | /******************************************************************************* | 
|  | 488 | * | 
|  | 489 | * FUNCTION:    acpi_tb_uninstall_table | 
|  | 490 | * | 
|  | 491 | * PARAMETERS:  table_info          - A table info struct | 
|  | 492 | * | 
|  | 493 | * RETURN:      Pointer to the next table in the list (of same type) | 
|  | 494 | * | 
|  | 495 | * DESCRIPTION: Free the memory associated with an internal ACPI table that | 
|  | 496 | *              is either installed or has never been installed. | 
|  | 497 | *              Table mutex should be locked. | 
|  | 498 | * | 
|  | 499 | ******************************************************************************/ | 
|  | 500 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 501 | struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc | 
|  | 502 | *table_desc) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 503 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 504 | struct acpi_table_desc *next_desc; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 505 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 506 | ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 507 |  | 
|  | 508 | if (!table_desc) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 509 | return_PTR(NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 510 | } | 
|  | 511 |  | 
|  | 512 | /* Unlink the descriptor from the doubly linked list */ | 
|  | 513 |  | 
|  | 514 | if (table_desc->prev) { | 
|  | 515 | table_desc->prev->next = table_desc->next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 516 | } else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 517 | /* Is first on list, update list head */ | 
|  | 518 |  | 
|  | 519 | acpi_gbl_table_lists[table_desc->type].next = table_desc->next; | 
|  | 520 | } | 
|  | 521 |  | 
|  | 522 | if (table_desc->next) { | 
|  | 523 | table_desc->next->prev = table_desc->prev; | 
|  | 524 | } | 
|  | 525 |  | 
|  | 526 | /* Free the memory allocated for the table itself */ | 
|  | 527 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 528 | acpi_tb_delete_single_table(table_desc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 529 |  | 
|  | 530 | /* Free the table descriptor */ | 
|  | 531 |  | 
|  | 532 | next_desc = table_desc->next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 533 | ACPI_MEM_FREE(table_desc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 534 |  | 
|  | 535 | /* Return pointer to the next descriptor */ | 
|  | 536 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 537 | return_PTR(next_desc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 538 | } |