diff options
Diffstat (limited to 'drivers/acpi/acpica/tbinstal.c')
-rw-r--r-- | drivers/acpi/acpica/tbinstal.c | 837 |
1 files changed, 316 insertions, 521 deletions
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index e3040947e9a0..d4d6029fef44 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
@@ -43,688 +43,483 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "acnamesp.h" | ||
47 | #include "actables.h" | 46 | #include "actables.h" |
48 | 47 | ||
49 | #define _COMPONENT ACPI_TABLES | 48 | #define _COMPONENT ACPI_TABLES |
50 | ACPI_MODULE_NAME("tbinstal") | 49 | ACPI_MODULE_NAME("tbinstal") |
51 | 50 | ||
52 | /****************************************************************************** | 51 | /* Local prototypes */ |
52 | static u8 | ||
53 | acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index); | ||
54 | |||
55 | /******************************************************************************* | ||
53 | * | 56 | * |
54 | * FUNCTION: acpi_tb_verify_table | 57 | * FUNCTION: acpi_tb_compare_tables |
55 | * | 58 | * |
56 | * PARAMETERS: table_desc - table | 59 | * PARAMETERS: table_desc - Table 1 descriptor to be compared |
60 | * table_index - Index of table 2 to be compared | ||
57 | * | 61 | * |
58 | * RETURN: Status | 62 | * RETURN: TRUE if both tables are identical. |
59 | * | 63 | * |
60 | * DESCRIPTION: this function is called to verify and map table | 64 | * DESCRIPTION: This function compares a table with another table that has |
65 | * already been installed in the root table list. | ||
61 | * | 66 | * |
62 | *****************************************************************************/ | 67 | ******************************************************************************/ |
63 | acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) | 68 | |
69 | static u8 | ||
70 | acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index) | ||
64 | { | 71 | { |
65 | acpi_status status = AE_OK; | 72 | acpi_status status = AE_OK; |
73 | u8 is_identical; | ||
74 | struct acpi_table_header *table; | ||
75 | u32 table_length; | ||
76 | u8 table_flags; | ||
66 | 77 | ||
67 | ACPI_FUNCTION_TRACE(tb_verify_table); | 78 | status = |
68 | 79 | acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], | |
69 | /* Map the table if necessary */ | 80 | &table, &table_length, &table_flags); |
70 | 81 | if (ACPI_FAILURE(status)) { | |
71 | if (!table_desc->pointer) { | 82 | return (FALSE); |
72 | if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == | ||
73 | ACPI_TABLE_ORIGIN_MAPPED) { | ||
74 | table_desc->pointer = | ||
75 | acpi_os_map_memory(table_desc->address, | ||
76 | table_desc->length); | ||
77 | } | ||
78 | if (!table_desc->pointer) { | ||
79 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
80 | } | ||
81 | } | 83 | } |
82 | 84 | ||
83 | /* Always calculate checksum, ignore bad checksum if requested */ | 85 | /* |
86 | * Check for a table match on the entire table length, | ||
87 | * not just the header. | ||
88 | */ | ||
89 | is_identical = (u8)((table_desc->length != table_length || | ||
90 | ACPI_MEMCMP(table_desc->pointer, table, | ||
91 | table_length)) ? FALSE : TRUE); | ||
84 | 92 | ||
85 | status = | 93 | /* Release the acquired table */ |
86 | acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); | ||
87 | 94 | ||
88 | return_ACPI_STATUS(status); | 95 | acpi_tb_release_table(table, table_length, table_flags); |
96 | return (is_identical); | ||
89 | } | 97 | } |
90 | 98 | ||
91 | /******************************************************************************* | 99 | /******************************************************************************* |
92 | * | 100 | * |
93 | * FUNCTION: acpi_tb_add_table | 101 | * FUNCTION: acpi_tb_install_table_with_override |
94 | * | 102 | * |
95 | * PARAMETERS: table_desc - Table descriptor | 103 | * PARAMETERS: table_index - Index into root table array |
96 | * table_index - Where the table index is returned | 104 | * new_table_desc - New table descriptor to install |
105 | * override - Whether override should be performed | ||
97 | * | 106 | * |
98 | * RETURN: Status | 107 | * RETURN: None |
99 | * | 108 | * |
100 | * DESCRIPTION: This function is called to add an ACPI table. It is used to | 109 | * DESCRIPTION: Install an ACPI table into the global data structure. The |
101 | * dynamically load tables via the Load and load_table AML | 110 | * table override mechanism is called to allow the host |
102 | * operators. | 111 | * OS to replace any table before it is installed in the root |
112 | * table array. | ||
103 | * | 113 | * |
104 | ******************************************************************************/ | 114 | ******************************************************************************/ |
105 | 115 | ||
106 | acpi_status | 116 | void |
107 | acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | 117 | acpi_tb_install_table_with_override(u32 table_index, |
118 | struct acpi_table_desc *new_table_desc, | ||
119 | u8 override) | ||
108 | { | 120 | { |
109 | u32 i; | ||
110 | acpi_status status = AE_OK; | ||
111 | 121 | ||
112 | ACPI_FUNCTION_TRACE(tb_add_table); | 122 | if (table_index >= acpi_gbl_root_table_list.current_table_count) { |
113 | 123 | return; | |
114 | if (!table_desc->pointer) { | ||
115 | status = acpi_tb_verify_table(table_desc); | ||
116 | if (ACPI_FAILURE(status) || !table_desc->pointer) { | ||
117 | return_ACPI_STATUS(status); | ||
118 | } | ||
119 | } | 124 | } |
120 | 125 | ||
121 | /* | 126 | /* |
122 | * Validate the incoming table signature. | 127 | * ACPI Table Override: |
123 | * | 128 | * |
124 | * 1) Originally, we checked the table signature for "SSDT" or "PSDT". | 129 | * Before we install the table, let the host OS override it with a new |
125 | * 2) We added support for OEMx tables, signature "OEM". | 130 | * one if desired. Any table within the RSDT/XSDT can be replaced, |
126 | * 3) Valid tables were encountered with a null signature, so we just | 131 | * including the DSDT which is pointed to by the FADT. |
127 | * gave up on validating the signature, (05/2008). | ||
128 | * 4) We encountered non-AML tables such as the MADT, which caused | ||
129 | * interpreter errors and kernel faults. So now, we once again allow | ||
130 | * only "SSDT", "OEMx", and now, also a null signature. (05/2011). | ||
131 | */ | 132 | */ |
132 | if ((table_desc->pointer->signature[0] != 0x00) && | 133 | if (override) { |
133 | (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) | 134 | acpi_tb_override_table(new_table_desc); |
134 | && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { | ||
135 | ACPI_BIOS_ERROR((AE_INFO, | ||
136 | "Table has invalid signature [%4.4s] (0x%8.8X), " | ||
137 | "must be SSDT or OEMx", | ||
138 | acpi_ut_valid_acpi_name(table_desc->pointer-> | ||
139 | signature) ? | ||
140 | table_desc->pointer->signature : "????", | ||
141 | *(u32 *)table_desc->pointer->signature)); | ||
142 | |||
143 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | ||
144 | } | 135 | } |
145 | 136 | ||
146 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 137 | acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. |
138 | tables[table_index], | ||
139 | new_table_desc->address, | ||
140 | new_table_desc->flags, | ||
141 | new_table_desc->pointer); | ||
147 | 142 | ||
148 | /* Check if table is already registered */ | 143 | acpi_tb_print_table_header(new_table_desc->address, |
144 | new_table_desc->pointer); | ||
149 | 145 | ||
150 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { | 146 | /* Set the global integer width (based upon revision of the DSDT) */ |
151 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
152 | status = | ||
153 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
154 | tables[i]); | ||
155 | if (ACPI_FAILURE(status) | ||
156 | || !acpi_gbl_root_table_list.tables[i].pointer) { | ||
157 | continue; | ||
158 | } | ||
159 | } | ||
160 | 147 | ||
161 | /* | 148 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
162 | * Check for a table match on the entire table length, | 149 | acpi_ut_set_integer_width(new_table_desc->pointer->revision); |
163 | * not just the header. | ||
164 | */ | ||
165 | if (table_desc->length != | ||
166 | acpi_gbl_root_table_list.tables[i].length) { | ||
167 | continue; | ||
168 | } | ||
169 | |||
170 | if (ACPI_MEMCMP(table_desc->pointer, | ||
171 | acpi_gbl_root_table_list.tables[i].pointer, | ||
172 | acpi_gbl_root_table_list.tables[i].length)) { | ||
173 | continue; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Note: the current mechanism does not unregister a table if it is | ||
178 | * dynamically unloaded. The related namespace entries are deleted, | ||
179 | * but the table remains in the root table list. | ||
180 | * | ||
181 | * The assumption here is that the number of different tables that | ||
182 | * will be loaded is actually small, and there is minimal overhead | ||
183 | * in just keeping the table in case it is needed again. | ||
184 | * | ||
185 | * If this assumption changes in the future (perhaps on large | ||
186 | * machines with many table load/unload operations), tables will | ||
187 | * need to be unregistered when they are unloaded, and slots in the | ||
188 | * root table list should be reused when empty. | ||
189 | */ | ||
190 | |||
191 | /* | ||
192 | * Table is already registered. | ||
193 | * We can delete the table that was passed as a parameter. | ||
194 | */ | ||
195 | acpi_tb_delete_table(table_desc); | ||
196 | *table_index = i; | ||
197 | |||
198 | if (acpi_gbl_root_table_list.tables[i]. | ||
199 | flags & ACPI_TABLE_IS_LOADED) { | ||
200 | |||
201 | /* Table is still loaded, this is an error */ | ||
202 | |||
203 | status = AE_ALREADY_EXISTS; | ||
204 | goto release; | ||
205 | } else { | ||
206 | /* Table was unloaded, allow it to be reloaded */ | ||
207 | |||
208 | table_desc->pointer = | ||
209 | acpi_gbl_root_table_list.tables[i].pointer; | ||
210 | table_desc->address = | ||
211 | acpi_gbl_root_table_list.tables[i].address; | ||
212 | status = AE_OK; | ||
213 | goto print_header; | ||
214 | } | ||
215 | } | 150 | } |
216 | |||
217 | /* | ||
218 | * ACPI Table Override: | ||
219 | * Allow the host to override dynamically loaded tables. | ||
220 | * NOTE: the table is fully mapped at this point, and the mapping will | ||
221 | * be deleted by tb_table_override if the table is actually overridden. | ||
222 | */ | ||
223 | (void)acpi_tb_table_override(table_desc->pointer, table_desc); | ||
224 | |||
225 | /* Add the table to the global root table list */ | ||
226 | |||
227 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, | ||
228 | table_desc->length, table_desc->flags, | ||
229 | table_index); | ||
230 | if (ACPI_FAILURE(status)) { | ||
231 | goto release; | ||
232 | } | ||
233 | |||
234 | print_header: | ||
235 | acpi_tb_print_table_header(table_desc->address, table_desc->pointer); | ||
236 | |||
237 | release: | ||
238 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
239 | return_ACPI_STATUS(status); | ||
240 | } | 151 | } |
241 | 152 | ||
242 | /******************************************************************************* | 153 | /******************************************************************************* |
243 | * | 154 | * |
244 | * FUNCTION: acpi_tb_table_override | 155 | * FUNCTION: acpi_tb_install_fixed_table |
245 | * | 156 | * |
246 | * PARAMETERS: table_header - Header for the original table | 157 | * PARAMETERS: address - Physical address of DSDT or FACS |
247 | * table_desc - Table descriptor initialized for the | 158 | * signature - Table signature, NULL if no need to |
248 | * original table. May or may not be mapped. | 159 | * match |
160 | * table_index - Index into root table array | ||
249 | * | 161 | * |
250 | * RETURN: Pointer to the entire new table. NULL if table not overridden. | 162 | * RETURN: Status |
251 | * If overridden, installs the new table within the input table | ||
252 | * descriptor. | ||
253 | * | 163 | * |
254 | * DESCRIPTION: Attempt table override by calling the OSL override functions. | 164 | * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data |
255 | * Note: If the table is overridden, then the entire new table | 165 | * structure. |
256 | * is mapped and returned by this function. | ||
257 | * | 166 | * |
258 | ******************************************************************************/ | 167 | ******************************************************************************/ |
259 | 168 | ||
260 | struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header | 169 | acpi_status |
261 | *table_header, | 170 | acpi_tb_install_fixed_table(acpi_physical_address address, |
262 | struct acpi_table_desc | 171 | char *signature, u32 table_index) |
263 | *table_desc) | ||
264 | { | 172 | { |
173 | struct acpi_table_desc new_table_desc; | ||
265 | acpi_status status; | 174 | acpi_status status; |
266 | struct acpi_table_header *new_table = NULL; | ||
267 | acpi_physical_address new_address = 0; | ||
268 | u32 new_table_length = 0; | ||
269 | u8 new_flags; | ||
270 | char *override_type; | ||
271 | 175 | ||
272 | /* (1) Attempt logical override (returns a logical address) */ | 176 | ACPI_FUNCTION_TRACE(tb_install_fixed_table); |
273 | 177 | ||
274 | status = acpi_os_table_override(table_header, &new_table); | 178 | if (!address) { |
275 | if (ACPI_SUCCESS(status) && new_table) { | 179 | ACPI_ERROR((AE_INFO, |
276 | new_address = ACPI_PTR_TO_PHYSADDR(new_table); | 180 | "Null physical address for ACPI table [%s]", |
277 | new_table_length = new_table->length; | 181 | signature)); |
278 | new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; | 182 | return (AE_NO_MEMORY); |
279 | override_type = "Logical"; | ||
280 | goto finish_override; | ||
281 | } | 183 | } |
282 | 184 | ||
283 | /* (2) Attempt physical override (returns a physical address) */ | 185 | /* Fill a table descriptor for validation */ |
284 | 186 | ||
285 | status = acpi_os_physical_table_override(table_header, | 187 | status = acpi_tb_acquire_temp_table(&new_table_desc, address, |
286 | &new_address, | 188 | ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); |
287 | &new_table_length); | 189 | if (ACPI_FAILURE(status)) { |
288 | if (ACPI_SUCCESS(status) && new_address && new_table_length) { | 190 | ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", |
289 | 191 | ACPI_CAST_PTR(void, address))); | |
290 | /* Map the entire new table */ | 192 | return_ACPI_STATUS(status); |
291 | |||
292 | new_table = acpi_os_map_memory(new_address, new_table_length); | ||
293 | if (!new_table) { | ||
294 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, | ||
295 | "%4.4s " ACPI_PRINTF_UINT | ||
296 | " Attempted physical table override failed", | ||
297 | table_header->signature, | ||
298 | ACPI_FORMAT_TO_UINT(table_desc-> | ||
299 | address))); | ||
300 | return (NULL); | ||
301 | } | ||
302 | |||
303 | override_type = "Physical"; | ||
304 | new_flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
305 | goto finish_override; | ||
306 | } | 193 | } |
307 | 194 | ||
308 | return (NULL); /* There was no override */ | 195 | /* Validate and verify a table before installation */ |
309 | |||
310 | finish_override: | ||
311 | |||
312 | ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT | ||
313 | " %s table override, new table: " ACPI_PRINTF_UINT, | ||
314 | table_header->signature, | ||
315 | ACPI_FORMAT_TO_UINT(table_desc->address), | ||
316 | override_type, ACPI_FORMAT_TO_UINT(new_table))); | ||
317 | 196 | ||
318 | /* We can now unmap/delete the original table (if fully mapped) */ | 197 | status = acpi_tb_verify_table(&new_table_desc, signature); |
198 | if (ACPI_FAILURE(status)) { | ||
199 | goto release_and_exit; | ||
200 | } | ||
319 | 201 | ||
320 | acpi_tb_delete_table(table_desc); | 202 | acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE); |
321 | 203 | ||
322 | /* Setup descriptor for the new table */ | 204 | release_and_exit: |
323 | 205 | ||
324 | table_desc->address = new_address; | 206 | /* Release the temporary table descriptor */ |
325 | table_desc->pointer = new_table; | ||
326 | table_desc->length = new_table_length; | ||
327 | table_desc->flags = new_flags; | ||
328 | 207 | ||
329 | return (new_table); | 208 | acpi_tb_release_temp_table(&new_table_desc); |
209 | return_ACPI_STATUS(status); | ||
330 | } | 210 | } |
331 | 211 | ||
332 | /******************************************************************************* | 212 | /******************************************************************************* |
333 | * | 213 | * |
334 | * FUNCTION: acpi_tb_resize_root_table_list | 214 | * FUNCTION: acpi_tb_install_standard_table |
335 | * | 215 | * |
336 | * PARAMETERS: None | 216 | * PARAMETERS: address - Address of the table (might be a virtual |
217 | * address depending on the table_flags) | ||
218 | * flags - Flags for the table | ||
219 | * reload - Whether reload should be performed | ||
220 | * override - Whether override should be performed | ||
221 | * table_index - Where the table index is returned | ||
337 | * | 222 | * |
338 | * RETURN: Status | 223 | * RETURN: Status |
339 | * | 224 | * |
340 | * DESCRIPTION: Expand the size of global table array | 225 | * DESCRIPTION: This function is called to install an ACPI table that is |
226 | * neither DSDT nor FACS (a "standard" table.) | ||
227 | * When this function is called by "Load" or "LoadTable" opcodes, | ||
228 | * or by acpi_load_table() API, the "Reload" parameter is set. | ||
229 | * After sucessfully returning from this function, table is | ||
230 | * "INSTALLED" but not "VALIDATED". | ||
341 | * | 231 | * |
342 | ******************************************************************************/ | 232 | ******************************************************************************/ |
343 | 233 | ||
344 | acpi_status acpi_tb_resize_root_table_list(void) | 234 | acpi_status |
235 | acpi_tb_install_standard_table(acpi_physical_address address, | ||
236 | u8 flags, | ||
237 | u8 reload, u8 override, u32 *table_index) | ||
345 | { | 238 | { |
346 | struct acpi_table_desc *tables; | 239 | u32 i; |
347 | u32 table_count; | 240 | acpi_status status = AE_OK; |
348 | 241 | struct acpi_table_desc new_table_desc; | |
349 | ACPI_FUNCTION_TRACE(tb_resize_root_table_list); | ||
350 | |||
351 | /* allow_resize flag is a parameter to acpi_initialize_tables */ | ||
352 | 242 | ||
353 | if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { | 243 | ACPI_FUNCTION_TRACE(tb_install_standard_table); |
354 | ACPI_ERROR((AE_INFO, | ||
355 | "Resize of Root Table Array is not allowed")); | ||
356 | return_ACPI_STATUS(AE_SUPPORT); | ||
357 | } | ||
358 | 244 | ||
359 | /* Increase the Table Array size */ | 245 | /* Acquire a temporary table descriptor for validation */ |
360 | 246 | ||
361 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | 247 | status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); |
362 | table_count = acpi_gbl_root_table_list.max_table_count; | 248 | if (ACPI_FAILURE(status)) { |
363 | } else { | 249 | ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", |
364 | table_count = acpi_gbl_root_table_list.current_table_count; | 250 | ACPI_CAST_PTR(void, address))); |
251 | return_ACPI_STATUS(status); | ||
365 | } | 252 | } |
366 | 253 | ||
367 | tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + | 254 | /* |
368 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * | 255 | * Optionally do not load any SSDTs from the RSDT/XSDT. This can |
369 | sizeof(struct acpi_table_desc)); | 256 | * be useful for debugging ACPI problems on some machines. |
370 | if (!tables) { | 257 | */ |
371 | ACPI_ERROR((AE_INFO, | 258 | if (!reload && |
372 | "Could not allocate new root table array")); | 259 | acpi_gbl_disable_ssdt_table_install && |
373 | return_ACPI_STATUS(AE_NO_MEMORY); | 260 | ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { |
261 | ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p", | ||
262 | new_table_desc.signature.ascii, ACPI_CAST_PTR(void, | ||
263 | address))); | ||
264 | goto release_and_exit; | ||
374 | } | 265 | } |
375 | 266 | ||
376 | /* Copy and free the previous table array */ | 267 | /* Validate and verify a table before installation */ |
377 | |||
378 | if (acpi_gbl_root_table_list.tables) { | ||
379 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, | ||
380 | (acpi_size) table_count * | ||
381 | sizeof(struct acpi_table_desc)); | ||
382 | 268 | ||
383 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | 269 | status = acpi_tb_verify_table(&new_table_desc, NULL); |
384 | ACPI_FREE(acpi_gbl_root_table_list.tables); | 270 | if (ACPI_FAILURE(status)) { |
385 | } | 271 | goto release_and_exit; |
386 | } | 272 | } |
387 | 273 | ||
388 | acpi_gbl_root_table_list.tables = tables; | 274 | if (reload) { |
389 | acpi_gbl_root_table_list.max_table_count = | 275 | /* |
390 | table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; | 276 | * Validate the incoming table signature. |
391 | acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; | 277 | * |
392 | 278 | * 1) Originally, we checked the table signature for "SSDT" or "PSDT". | |
393 | return_ACPI_STATUS(AE_OK); | 279 | * 2) We added support for OEMx tables, signature "OEM". |
394 | } | 280 | * 3) Valid tables were encountered with a null signature, so we just |
395 | 281 | * gave up on validating the signature, (05/2008). | |
396 | /******************************************************************************* | 282 | * 4) We encountered non-AML tables such as the MADT, which caused |
397 | * | 283 | * interpreter errors and kernel faults. So now, we once again allow |
398 | * FUNCTION: acpi_tb_store_table | 284 | * only "SSDT", "OEMx", and now, also a null signature. (05/2011). |
399 | * | 285 | */ |
400 | * PARAMETERS: address - Table address | 286 | if ((new_table_desc.signature.ascii[0] != 0x00) && |
401 | * table - Table header | 287 | (!ACPI_COMPARE_NAME |
402 | * length - Table length | 288 | (&new_table_desc.signature, ACPI_SIG_SSDT)) |
403 | * flags - flags | 289 | && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) |
404 | * | 290 | { |
405 | * RETURN: Status and table index. | 291 | ACPI_BIOS_ERROR((AE_INFO, |
406 | * | 292 | "Table has invalid signature [%4.4s] (0x%8.8X), " |
407 | * DESCRIPTION: Add an ACPI table to the global table list | 293 | "must be SSDT or OEMx", |
408 | * | 294 | acpi_ut_valid_acpi_name(new_table_desc. |
409 | ******************************************************************************/ | 295 | signature. |
296 | ascii) ? | ||
297 | new_table_desc.signature. | ||
298 | ascii : "????", | ||
299 | new_table_desc.signature.integer)); | ||
300 | |||
301 | status = AE_BAD_SIGNATURE; | ||
302 | goto release_and_exit; | ||
303 | } | ||
410 | 304 | ||
411 | acpi_status | 305 | /* Check if table is already registered */ |
412 | acpi_tb_store_table(acpi_physical_address address, | ||
413 | struct acpi_table_header *table, | ||
414 | u32 length, u8 flags, u32 *table_index) | ||
415 | { | ||
416 | acpi_status status; | ||
417 | struct acpi_table_desc *new_table; | ||
418 | 306 | ||
419 | /* Ensure that there is room for the table in the Root Table List */ | 307 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; |
308 | ++i) { | ||
309 | /* | ||
310 | * Check for a table match on the entire table length, | ||
311 | * not just the header. | ||
312 | */ | ||
313 | if (!acpi_tb_compare_tables(&new_table_desc, i)) { | ||
314 | continue; | ||
315 | } | ||
420 | 316 | ||
421 | if (acpi_gbl_root_table_list.current_table_count >= | 317 | /* |
422 | acpi_gbl_root_table_list.max_table_count) { | 318 | * Note: the current mechanism does not unregister a table if it is |
423 | status = acpi_tb_resize_root_table_list(); | 319 | * dynamically unloaded. The related namespace entries are deleted, |
424 | if (ACPI_FAILURE(status)) { | 320 | * but the table remains in the root table list. |
425 | return (status); | 321 | * |
322 | * The assumption here is that the number of different tables that | ||
323 | * will be loaded is actually small, and there is minimal overhead | ||
324 | * in just keeping the table in case it is needed again. | ||
325 | * | ||
326 | * If this assumption changes in the future (perhaps on large | ||
327 | * machines with many table load/unload operations), tables will | ||
328 | * need to be unregistered when they are unloaded, and slots in the | ||
329 | * root table list should be reused when empty. | ||
330 | */ | ||
331 | if (acpi_gbl_root_table_list.tables[i]. | ||
332 | flags & ACPI_TABLE_IS_LOADED) { | ||
333 | |||
334 | /* Table is still loaded, this is an error */ | ||
335 | |||
336 | status = AE_ALREADY_EXISTS; | ||
337 | goto release_and_exit; | ||
338 | } else { | ||
339 | /* | ||
340 | * Table was unloaded, allow it to be reloaded. | ||
341 | * As we are going to return AE_OK to the caller, we should | ||
342 | * take the responsibility of freeing the input descriptor. | ||
343 | * Refill the input descriptor to ensure | ||
344 | * acpi_tb_install_table_with_override() can be called again to | ||
345 | * indicate the re-installation. | ||
346 | */ | ||
347 | acpi_tb_uninstall_table(&new_table_desc); | ||
348 | *table_index = i; | ||
349 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
350 | return_ACPI_STATUS(AE_OK); | ||
351 | } | ||
426 | } | 352 | } |
427 | } | 353 | } |
428 | 354 | ||
429 | new_table = | 355 | /* Add the table to the global root table list */ |
430 | &acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. | ||
431 | current_table_count]; | ||
432 | |||
433 | /* Initialize added table */ | ||
434 | |||
435 | new_table->address = address; | ||
436 | new_table->pointer = table; | ||
437 | new_table->length = length; | ||
438 | new_table->owner_id = 0; | ||
439 | new_table->flags = flags; | ||
440 | |||
441 | ACPI_MOVE_32_TO_32(&new_table->signature, table->signature); | ||
442 | |||
443 | *table_index = acpi_gbl_root_table_list.current_table_count; | ||
444 | acpi_gbl_root_table_list.current_table_count++; | ||
445 | return (AE_OK); | ||
446 | } | ||
447 | |||
448 | /******************************************************************************* | ||
449 | * | ||
450 | * FUNCTION: acpi_tb_delete_table | ||
451 | * | ||
452 | * PARAMETERS: table_index - Table index | ||
453 | * | ||
454 | * RETURN: None | ||
455 | * | ||
456 | * DESCRIPTION: Delete one internal ACPI table | ||
457 | * | ||
458 | ******************************************************************************/ | ||
459 | 356 | ||
460 | void acpi_tb_delete_table(struct acpi_table_desc *table_desc) | 357 | status = acpi_tb_get_next_root_index(&i); |
461 | { | 358 | if (ACPI_FAILURE(status)) { |
462 | /* Table must be mapped or allocated */ | 359 | goto release_and_exit; |
463 | if (!table_desc->pointer) { | ||
464 | return; | ||
465 | } | 360 | } |
466 | switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { | ||
467 | case ACPI_TABLE_ORIGIN_MAPPED: | ||
468 | |||
469 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | ||
470 | break; | ||
471 | |||
472 | case ACPI_TABLE_ORIGIN_ALLOCATED: | ||
473 | 361 | ||
474 | ACPI_FREE(table_desc->pointer); | 362 | *table_index = i; |
475 | break; | 363 | acpi_tb_install_table_with_override(i, &new_table_desc, override); |
476 | 364 | ||
477 | /* Not mapped or allocated, there is nothing we can do */ | 365 | release_and_exit: |
478 | 366 | ||
479 | default: | 367 | /* Release the temporary table descriptor */ |
480 | 368 | ||
481 | return; | 369 | acpi_tb_release_temp_table(&new_table_desc); |
482 | } | 370 | return_ACPI_STATUS(status); |
483 | |||
484 | table_desc->pointer = NULL; | ||
485 | } | 371 | } |
486 | 372 | ||
487 | /******************************************************************************* | 373 | /******************************************************************************* |
488 | * | 374 | * |
489 | * FUNCTION: acpi_tb_terminate | 375 | * FUNCTION: acpi_tb_override_table |
490 | * | 376 | * |
491 | * PARAMETERS: None | 377 | * PARAMETERS: old_table_desc - Validated table descriptor to be |
378 | * overridden | ||
492 | * | 379 | * |
493 | * RETURN: None | 380 | * RETURN: None |
494 | * | 381 | * |
495 | * DESCRIPTION: Delete all internal ACPI tables | 382 | * DESCRIPTION: Attempt table override by calling the OSL override functions. |
383 | * Note: If the table is overridden, then the entire new table | ||
384 | * is acquired and returned by this function. | ||
385 | * Before/after invocation, the table descriptor is in a state | ||
386 | * that is "VALIDATED". | ||
496 | * | 387 | * |
497 | ******************************************************************************/ | 388 | ******************************************************************************/ |
498 | 389 | ||
499 | void acpi_tb_terminate(void) | 390 | void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) |
500 | { | 391 | { |
501 | u32 i; | 392 | acpi_status status; |
502 | 393 | char *override_type; | |
503 | ACPI_FUNCTION_TRACE(tb_terminate); | 394 | struct acpi_table_desc new_table_desc; |
504 | 395 | struct acpi_table_header *table; | |
505 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 396 | acpi_physical_address address; |
506 | 397 | u32 length; | |
507 | /* Delete the individual tables */ | ||
508 | 398 | ||
509 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { | 399 | /* (1) Attempt logical override (returns a logical address) */ |
510 | acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); | ||
511 | } | ||
512 | 400 | ||
513 | /* | 401 | status = acpi_os_table_override(old_table_desc->pointer, &table); |
514 | * Delete the root table array if allocated locally. Array cannot be | 402 | if (ACPI_SUCCESS(status) && table) { |
515 | * mapped, so we don't need to check for that flag. | 403 | acpi_tb_acquire_temp_table(&new_table_desc, |
516 | */ | 404 | ACPI_PTR_TO_PHYSADDR(table), |
517 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | 405 | ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); |
518 | ACPI_FREE(acpi_gbl_root_table_list.tables); | 406 | override_type = "Logical"; |
407 | goto finish_override; | ||
519 | } | 408 | } |
520 | 409 | ||
521 | acpi_gbl_root_table_list.tables = NULL; | 410 | /* (2) Attempt physical override (returns a physical address) */ |
522 | acpi_gbl_root_table_list.flags = 0; | ||
523 | acpi_gbl_root_table_list.current_table_count = 0; | ||
524 | 411 | ||
525 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); | 412 | status = acpi_os_physical_table_override(old_table_desc->pointer, |
526 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 413 | &address, &length); |
414 | if (ACPI_SUCCESS(status) && address && length) { | ||
415 | acpi_tb_acquire_temp_table(&new_table_desc, address, | ||
416 | ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); | ||
417 | override_type = "Physical"; | ||
418 | goto finish_override; | ||
419 | } | ||
527 | 420 | ||
528 | return_VOID; | 421 | return; /* There was no override */ |
529 | } | ||
530 | 422 | ||
531 | /******************************************************************************* | 423 | finish_override: |
532 | * | ||
533 | * FUNCTION: acpi_tb_delete_namespace_by_owner | ||
534 | * | ||
535 | * PARAMETERS: table_index - Table index | ||
536 | * | ||
537 | * RETURN: Status | ||
538 | * | ||
539 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. | ||
540 | * | ||
541 | ******************************************************************************/ | ||
542 | |||
543 | acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) | ||
544 | { | ||
545 | acpi_owner_id owner_id; | ||
546 | acpi_status status; | ||
547 | 424 | ||
548 | ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); | 425 | /* Validate and verify a table before overriding */ |
549 | 426 | ||
550 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 427 | status = acpi_tb_verify_table(&new_table_desc, NULL); |
551 | if (ACPI_FAILURE(status)) { | 428 | if (ACPI_FAILURE(status)) { |
552 | return_ACPI_STATUS(status); | 429 | return; |
553 | } | 430 | } |
554 | 431 | ||
555 | if (table_index >= acpi_gbl_root_table_list.current_table_count) { | 432 | ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT |
556 | 433 | " %s table override, new table: " ACPI_PRINTF_UINT, | |
557 | /* The table index does not exist */ | 434 | old_table_desc->signature.ascii, |
558 | 435 | ACPI_FORMAT_TO_UINT(old_table_desc->address), | |
559 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 436 | override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); |
560 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
561 | } | ||
562 | 437 | ||
563 | /* Get the owner ID for this table, used to delete namespace nodes */ | 438 | /* We can now uninstall the original table */ |
564 | 439 | ||
565 | owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; | 440 | acpi_tb_uninstall_table(old_table_desc); |
566 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
567 | 441 | ||
568 | /* | 442 | /* |
569 | * Need to acquire the namespace writer lock to prevent interference | 443 | * Replace the original table descriptor and keep its state as |
570 | * with any concurrent namespace walks. The interpreter must be | 444 | * "VALIDATED". |
571 | * released during the deletion since the acquisition of the deletion | ||
572 | * lock may block, and also since the execution of a namespace walk | ||
573 | * must be allowed to use the interpreter. | ||
574 | */ | 445 | */ |
575 | (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); | 446 | acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, |
576 | status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); | 447 | new_table_desc.flags, |
448 | new_table_desc.pointer); | ||
449 | acpi_tb_validate_table(old_table_desc); | ||
577 | 450 | ||
578 | acpi_ns_delete_namespace_by_owner(owner_id); | 451 | /* Release the temporary table descriptor */ |
579 | if (ACPI_FAILURE(status)) { | ||
580 | return_ACPI_STATUS(status); | ||
581 | } | ||
582 | 452 | ||
583 | acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); | 453 | acpi_tb_release_temp_table(&new_table_desc); |
584 | |||
585 | status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); | ||
586 | return_ACPI_STATUS(status); | ||
587 | } | 454 | } |
588 | 455 | ||
589 | /******************************************************************************* | 456 | /******************************************************************************* |
590 | * | 457 | * |
591 | * FUNCTION: acpi_tb_allocate_owner_id | 458 | * FUNCTION: acpi_tb_store_table |
592 | * | 459 | * |
593 | * PARAMETERS: table_index - Table index | 460 | * PARAMETERS: address - Table address |
461 | * table - Table header | ||
462 | * length - Table length | ||
463 | * flags - Install flags | ||
464 | * table_index - Where the table index is returned | ||
594 | * | 465 | * |
595 | * RETURN: Status | 466 | * RETURN: Status and table index. |
596 | * | 467 | * |
597 | * DESCRIPTION: Allocates owner_id in table_desc | 468 | * DESCRIPTION: Add an ACPI table to the global table list |
598 | * | 469 | * |
599 | ******************************************************************************/ | 470 | ******************************************************************************/ |
600 | 471 | ||
601 | acpi_status acpi_tb_allocate_owner_id(u32 table_index) | 472 | acpi_status |
473 | acpi_tb_store_table(acpi_physical_address address, | ||
474 | struct acpi_table_header * table, | ||
475 | u32 length, u8 flags, u32 *table_index) | ||
602 | { | 476 | { |
603 | acpi_status status = AE_BAD_PARAMETER; | 477 | acpi_status status; |
604 | 478 | struct acpi_table_desc *table_desc; | |
605 | ACPI_FUNCTION_TRACE(tb_allocate_owner_id); | ||
606 | 479 | ||
607 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 480 | status = acpi_tb_get_next_root_index(table_index); |
608 | if (table_index < acpi_gbl_root_table_list.current_table_count) { | 481 | if (ACPI_FAILURE(status)) { |
609 | status = acpi_ut_allocate_owner_id | 482 | return (status); |
610 | (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); | ||
611 | } | 483 | } |
612 | 484 | ||
613 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 485 | /* Initialize added table */ |
614 | return_ACPI_STATUS(status); | ||
615 | } | ||
616 | |||
617 | /******************************************************************************* | ||
618 | * | ||
619 | * FUNCTION: acpi_tb_release_owner_id | ||
620 | * | ||
621 | * PARAMETERS: table_index - Table index | ||
622 | * | ||
623 | * RETURN: Status | ||
624 | * | ||
625 | * DESCRIPTION: Releases owner_id in table_desc | ||
626 | * | ||
627 | ******************************************************************************/ | ||
628 | |||
629 | acpi_status acpi_tb_release_owner_id(u32 table_index) | ||
630 | { | ||
631 | acpi_status status = AE_BAD_PARAMETER; | ||
632 | |||
633 | ACPI_FUNCTION_TRACE(tb_release_owner_id); | ||
634 | |||
635 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
636 | if (table_index < acpi_gbl_root_table_list.current_table_count) { | ||
637 | acpi_ut_release_owner_id(& | ||
638 | (acpi_gbl_root_table_list. | ||
639 | tables[table_index].owner_id)); | ||
640 | status = AE_OK; | ||
641 | } | ||
642 | 486 | ||
643 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 487 | table_desc = &acpi_gbl_root_table_list.tables[*table_index]; |
644 | return_ACPI_STATUS(status); | 488 | acpi_tb_init_table_descriptor(table_desc, address, flags, table); |
489 | table_desc->pointer = table; | ||
490 | return (AE_OK); | ||
645 | } | 491 | } |
646 | 492 | ||
647 | /******************************************************************************* | 493 | /******************************************************************************* |
648 | * | 494 | * |
649 | * FUNCTION: acpi_tb_get_owner_id | 495 | * FUNCTION: acpi_tb_uninstall_table |
650 | * | 496 | * |
651 | * PARAMETERS: table_index - Table index | 497 | * PARAMETERS: table_desc - Table descriptor |
652 | * owner_id - Where the table owner_id is returned | ||
653 | * | 498 | * |
654 | * RETURN: Status | 499 | * RETURN: None |
655 | * | 500 | * |
656 | * DESCRIPTION: returns owner_id for the ACPI table | 501 | * DESCRIPTION: Delete one internal ACPI table |
657 | * | 502 | * |
658 | ******************************************************************************/ | 503 | ******************************************************************************/ |
659 | 504 | ||
660 | acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) | 505 | void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) |
661 | { | 506 | { |
662 | acpi_status status = AE_BAD_PARAMETER; | ||
663 | |||
664 | ACPI_FUNCTION_TRACE(tb_get_owner_id); | ||
665 | 507 | ||
666 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 508 | ACPI_FUNCTION_TRACE(tb_uninstall_table); |
667 | if (table_index < acpi_gbl_root_table_list.current_table_count) { | ||
668 | *owner_id = | ||
669 | acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
670 | status = AE_OK; | ||
671 | } | ||
672 | 509 | ||
673 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 510 | /* Table must be installed */ |
674 | return_ACPI_STATUS(status); | ||
675 | } | ||
676 | |||
677 | /******************************************************************************* | ||
678 | * | ||
679 | * FUNCTION: acpi_tb_is_table_loaded | ||
680 | * | ||
681 | * PARAMETERS: table_index - Table index | ||
682 | * | ||
683 | * RETURN: Table Loaded Flag | ||
684 | * | ||
685 | ******************************************************************************/ | ||
686 | 511 | ||
687 | u8 acpi_tb_is_table_loaded(u32 table_index) | 512 | if (!table_desc->address) { |
688 | { | 513 | return_VOID; |
689 | u8 is_loaded = FALSE; | ||
690 | |||
691 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
692 | if (table_index < acpi_gbl_root_table_list.current_table_count) { | ||
693 | is_loaded = (u8) | ||
694 | (acpi_gbl_root_table_list.tables[table_index].flags & | ||
695 | ACPI_TABLE_IS_LOADED); | ||
696 | } | 514 | } |
697 | 515 | ||
698 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 516 | acpi_tb_invalidate_table(table_desc); |
699 | return (is_loaded); | ||
700 | } | ||
701 | |||
702 | /******************************************************************************* | ||
703 | * | ||
704 | * FUNCTION: acpi_tb_set_table_loaded_flag | ||
705 | * | ||
706 | * PARAMETERS: table_index - Table index | ||
707 | * is_loaded - TRUE if table is loaded, FALSE otherwise | ||
708 | * | ||
709 | * RETURN: None | ||
710 | * | ||
711 | * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. | ||
712 | * | ||
713 | ******************************************************************************/ | ||
714 | |||
715 | void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) | ||
716 | { | ||
717 | 517 | ||
718 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 518 | if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == |
719 | if (table_index < acpi_gbl_root_table_list.current_table_count) { | 519 | ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { |
720 | if (is_loaded) { | 520 | ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); |
721 | acpi_gbl_root_table_list.tables[table_index].flags |= | ||
722 | ACPI_TABLE_IS_LOADED; | ||
723 | } else { | ||
724 | acpi_gbl_root_table_list.tables[table_index].flags &= | ||
725 | ~ACPI_TABLE_IS_LOADED; | ||
726 | } | ||
727 | } | 521 | } |
728 | 522 | ||
729 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 523 | table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); |
524 | return_VOID; | ||
730 | } | 525 | } |