Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 : : /****************************************************************************** 3 : : * 4 : : * Module Name: tbxface - ACPI table-oriented external interfaces 5 : : * 6 : : * Copyright (C) 2000 - 2020, Intel Corp. 7 : : * 8 : : *****************************************************************************/ 9 : : 10 : : #define EXPORT_ACPI_INTERFACES 11 : : 12 : : #include <acpi/acpi.h> 13 : : #include "accommon.h" 14 : : #include "actables.h" 15 : : 16 : : #define _COMPONENT ACPI_TABLES 17 : : ACPI_MODULE_NAME("tbxface") 18 : : 19 : : /******************************************************************************* 20 : : * 21 : : * FUNCTION: acpi_allocate_root_table 22 : : * 23 : : * PARAMETERS: initial_table_count - Size of initial_table_array, in number of 24 : : * struct acpi_table_desc structures 25 : : * 26 : : * RETURN: Status 27 : : * 28 : : * DESCRIPTION: Allocate a root table array. Used by iASL compiler and 29 : : * acpi_initialize_tables. 30 : : * 31 : : ******************************************************************************/ 32 : 0 : acpi_status acpi_allocate_root_table(u32 initial_table_count) 33 : : { 34 : : 35 : 0 : acpi_gbl_root_table_list.max_table_count = initial_table_count; 36 : 0 : acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; 37 : : 38 : 0 : return (acpi_tb_resize_root_table_list()); 39 : : } 40 : : 41 : : /******************************************************************************* 42 : : * 43 : : * FUNCTION: acpi_initialize_tables 44 : : * 45 : : * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated 46 : : * struct acpi_table_desc structures. If NULL, the 47 : : * array is dynamically allocated. 48 : : * initial_table_count - Size of initial_table_array, in number of 49 : : * struct acpi_table_desc structures 50 : : * allow_resize - Flag to tell Table Manager if resize of 51 : : * pre-allocated array is allowed. Ignored 52 : : * if initial_table_array is NULL. 53 : : * 54 : : * RETURN: Status 55 : : * 56 : : * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. 57 : : * 58 : : * NOTE: Allows static allocation of the initial table array in order 59 : : * to avoid the use of dynamic memory in confined environments 60 : : * such as the kernel boot sequence where it may not be available. 61 : : * 62 : : * If the host OS memory managers are initialized, use NULL for 63 : : * initial_table_array, and the table will be dynamically allocated. 64 : : * 65 : : ******************************************************************************/ 66 : : 67 : : acpi_status ACPI_INIT_FUNCTION 68 : 11 : acpi_initialize_tables(struct acpi_table_desc *initial_table_array, 69 : : u32 initial_table_count, u8 allow_resize) 70 : : { 71 : 11 : acpi_physical_address rsdp_address; 72 : 11 : acpi_status status; 73 : : 74 : 11 : ACPI_FUNCTION_TRACE(acpi_initialize_tables); 75 : : 76 : : /* 77 : : * Setup the Root Table Array and allocate the table array 78 : : * if requested 79 : : */ 80 [ - + ]: 11 : if (!initial_table_array) { 81 : 0 : status = acpi_allocate_root_table(initial_table_count); 82 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 83 : : return_ACPI_STATUS(status); 84 : : } 85 : : } else { 86 : : /* Root Table Array has been statically allocated by the host */ 87 : : 88 : 11 : memset(initial_table_array, 0, 89 : 11 : (acpi_size)initial_table_count * 90 : : sizeof(struct acpi_table_desc)); 91 : : 92 : 11 : acpi_gbl_root_table_list.tables = initial_table_array; 93 : 11 : acpi_gbl_root_table_list.max_table_count = initial_table_count; 94 : 11 : acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; 95 [ - + ]: 11 : if (allow_resize) { 96 : 0 : acpi_gbl_root_table_list.flags |= 97 : : ACPI_ROOT_ALLOW_RESIZE; 98 : : } 99 : : } 100 : : 101 : : /* Get the address of the RSDP */ 102 : : 103 : 11 : rsdp_address = acpi_os_get_root_pointer(); 104 [ + - ]: 11 : if (!rsdp_address) { 105 : : return_ACPI_STATUS(AE_NOT_FOUND); 106 : : } 107 : : 108 : : /* 109 : : * Get the root table (RSDT or XSDT) and extract all entries to the local 110 : : * Root Table Array. This array contains the information of the RSDT/XSDT 111 : : * in a common, more usable format. 112 : : */ 113 : 11 : status = acpi_tb_parse_root_table(rsdp_address); 114 : 11 : return_ACPI_STATUS(status); 115 : : } 116 : : 117 : : ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) 118 : : 119 : : /******************************************************************************* 120 : : * 121 : : * FUNCTION: acpi_reallocate_root_table 122 : : * 123 : : * PARAMETERS: None 124 : : * 125 : : * RETURN: Status 126 : : * 127 : : * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the 128 : : * root list from the previously provided scratch area. Should 129 : : * be called once dynamic memory allocation is available in the 130 : : * kernel. 131 : : * 132 : : ******************************************************************************/ 133 : 11 : acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void) 134 : : { 135 : 11 : acpi_status status; 136 : 11 : struct acpi_table_desc *table_desc; 137 : 11 : u32 i, j; 138 : : 139 : 11 : ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); 140 : : 141 : : /* 142 : : * If there are tables unverified, it is required to reallocate the 143 : : * root table list to clean up invalid table entries. Otherwise only 144 : : * reallocate the root table list if the host provided a static buffer 145 : : * for the table array in the call to acpi_initialize_tables(). 146 : : */ 147 [ - + - - ]: 11 : if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) && 148 : : acpi_gbl_enable_table_validation) { 149 : : return_ACPI_STATUS(AE_SUPPORT); 150 : : } 151 : : 152 : 11 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 153 : : 154 : : /* 155 : : * Ensure OS early boot logic, which is required by some hosts. If the 156 : : * table state is reported to be wrong, developers should fix the 157 : : * issue by invoking acpi_put_table() for the reported table during the 158 : : * early stage. 159 : : */ 160 [ + + ]: 77 : for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { 161 : 55 : table_desc = &acpi_gbl_root_table_list.tables[i]; 162 [ - + ]: 55 : if (table_desc->pointer) { 163 : 0 : ACPI_ERROR((AE_INFO, 164 : : "Table [%4.4s] is not invalidated during early boot stage", 165 : : table_desc->signature.ascii)); 166 : : } 167 : : } 168 : : 169 [ + - ]: 11 : if (!acpi_gbl_enable_table_validation) { 170 : : /* 171 : : * Now it's safe to do full table validation. We can do deferred 172 : : * table initialization here once the flag is set. 173 : : */ 174 : 11 : acpi_gbl_enable_table_validation = TRUE; 175 [ + + ]: 66 : for (i = 0; i < acpi_gbl_root_table_list.current_table_count; 176 : 55 : ++i) { 177 : 55 : table_desc = &acpi_gbl_root_table_list.tables[i]; 178 [ + - ]: 55 : if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) { 179 : 55 : status = 180 : 55 : acpi_tb_verify_temp_table(table_desc, NULL, 181 : : &j); 182 [ - + ]: 55 : if (ACPI_FAILURE(status)) { 183 : 0 : acpi_tb_uninstall_table(table_desc); 184 : : } 185 : : } 186 : : } 187 : : } 188 : : 189 : 11 : acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE; 190 : 11 : status = acpi_tb_resize_root_table_list(); 191 : 11 : acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; 192 : : 193 : 11 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 194 : 11 : return_ACPI_STATUS(status); 195 : : } 196 : : 197 : : ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table) 198 : : 199 : : /******************************************************************************* 200 : : * 201 : : * FUNCTION: acpi_get_table_header 202 : : * 203 : : * PARAMETERS: signature - ACPI signature of needed table 204 : : * instance - Which instance (for SSDTs) 205 : : * out_table_header - The pointer to the table header to fill 206 : : * 207 : : * RETURN: Status and pointer to mapped table header 208 : : * 209 : : * DESCRIPTION: Finds an ACPI table header. 210 : : * 211 : : * NOTE: Caller is responsible in unmapping the header with 212 : : * acpi_os_unmap_memory 213 : : * 214 : : ******************************************************************************/ 215 : : acpi_status 216 : 44 : acpi_get_table_header(char *signature, 217 : : u32 instance, struct acpi_table_header *out_table_header) 218 : : { 219 : 44 : u32 i; 220 : 44 : u32 j; 221 : 44 : struct acpi_table_header *header; 222 : : 223 : : /* Parameter validation */ 224 : : 225 [ + - ]: 44 : if (!signature || !out_table_header) { 226 : : return (AE_BAD_PARAMETER); 227 : : } 228 : : 229 : : /* Walk the root table list */ 230 : : 231 [ + - ]: 88 : for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count; 232 : 44 : i++) { 233 [ + + ]: 88 : if (!ACPI_COMPARE_NAMESEG 234 : : (&(acpi_gbl_root_table_list.tables[i].signature), 235 : : signature)) { 236 : 44 : continue; 237 : : } 238 : : 239 [ - + ]: 44 : if (++j < instance) { 240 : 0 : continue; 241 : : } 242 : : 243 [ + - ]: 44 : if (!acpi_gbl_root_table_list.tables[i].pointer) { 244 [ + - ]: 44 : if ((acpi_gbl_root_table_list.tables[i].flags & 245 : : ACPI_TABLE_ORIGIN_MASK) == 246 : : ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) { 247 : 44 : header = 248 : 44 : acpi_os_map_memory(acpi_gbl_root_table_list. 249 : : tables[i].address, 250 : : sizeof(struct 251 : : acpi_table_header)); 252 [ + - ]: 44 : if (!header) { 253 : : return (AE_NO_MEMORY); 254 : : } 255 : : 256 : 44 : memcpy(out_table_header, header, 257 : : sizeof(struct acpi_table_header)); 258 : 44 : acpi_os_unmap_memory(header, 259 : : sizeof(struct 260 : : acpi_table_header)); 261 : : } else { 262 : : return (AE_NOT_FOUND); 263 : : } 264 : : } else { 265 : 0 : memcpy(out_table_header, 266 : : acpi_gbl_root_table_list.tables[i].pointer, 267 : : sizeof(struct acpi_table_header)); 268 : : } 269 : : return (AE_OK); 270 : : } 271 : : 272 : : return (AE_NOT_FOUND); 273 : : } 274 : : 275 : : ACPI_EXPORT_SYMBOL(acpi_get_table_header) 276 : : 277 : : /******************************************************************************* 278 : : * 279 : : * FUNCTION: acpi_get_table 280 : : * 281 : : * PARAMETERS: signature - ACPI signature of needed table 282 : : * instance - Which instance (for SSDTs) 283 : : * out_table - Where the pointer to the table is returned 284 : : * 285 : : * RETURN: Status and pointer to the requested table 286 : : * 287 : : * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the 288 : : * RSDT/XSDT. 289 : : * Note that an early stage acpi_get_table() call must be paired 290 : : * with an early stage acpi_put_table() call. otherwise the table 291 : : * pointer mapped by the early stage mapping implementation may be 292 : : * erroneously unmapped by the late stage unmapping implementation 293 : : * in an acpi_put_table() invoked during the late stage. 294 : : * 295 : : ******************************************************************************/ 296 : : acpi_status 297 : 363 : acpi_get_table(char *signature, 298 : : u32 instance, struct acpi_table_header ** out_table) 299 : : { 300 : 363 : u32 i; 301 : 363 : u32 j; 302 : 363 : acpi_status status = AE_NOT_FOUND; 303 : 363 : struct acpi_table_desc *table_desc; 304 : : 305 : : /* Parameter validation */ 306 : : 307 [ + - ]: 363 : if (!signature || !out_table) { 308 : : return (AE_BAD_PARAMETER); 309 : : } 310 : : 311 : : /* 312 : : * Note that the following line is required by some OSPMs, they only 313 : : * check if the returned table is NULL instead of the returned status 314 : : * to determined if this function is succeeded. 315 : : */ 316 : 363 : *out_table = NULL; 317 : : 318 : 363 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 319 : : 320 : : /* Walk the root table list */ 321 : : 322 [ + + ]: 2222 : for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count; 323 : 1496 : i++) { 324 : 1639 : table_desc = &acpi_gbl_root_table_list.tables[i]; 325 : : 326 [ + + ]: 1639 : if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) { 327 : 1430 : continue; 328 : : } 329 : : 330 [ + + ]: 209 : if (++j < instance) { 331 : 66 : continue; 332 : : } 333 : : 334 : 143 : status = acpi_tb_get_table(table_desc, out_table); 335 : 143 : break; 336 : : } 337 : : 338 : 363 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 339 : 363 : return (status); 340 : : } 341 : : 342 : : ACPI_EXPORT_SYMBOL(acpi_get_table) 343 : : 344 : : /******************************************************************************* 345 : : * 346 : : * FUNCTION: acpi_put_table 347 : : * 348 : : * PARAMETERS: table - The pointer to the table 349 : : * 350 : : * RETURN: None 351 : : * 352 : : * DESCRIPTION: Release a table returned by acpi_get_table() and its clones. 353 : : * Note that it is not safe if this function was invoked after an 354 : : * uninstallation happened to the original table descriptor. 355 : : * Currently there is no OSPMs' requirement to handle such 356 : : * situations. 357 : : * 358 : : ******************************************************************************/ 359 : 132 : void acpi_put_table(struct acpi_table_header *table) 360 : : { 361 : 132 : u32 i; 362 : 132 : struct acpi_table_desc *table_desc; 363 : : 364 : 132 : ACPI_FUNCTION_TRACE(acpi_put_table); 365 : : 366 [ + - ]: 132 : if (!table) { 367 : : return_VOID; 368 : : } 369 : : 370 : 132 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 371 : : 372 : : /* Walk the root table list */ 373 : : 374 [ + - ]: 638 : for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { 375 : 506 : table_desc = &acpi_gbl_root_table_list.tables[i]; 376 : : 377 [ + + ]: 506 : if (table_desc->pointer != table) { 378 : 374 : continue; 379 : : } 380 : : 381 : 132 : acpi_tb_put_table(table_desc); 382 : 132 : break; 383 : : } 384 : : 385 : 132 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 386 : 132 : return_VOID; 387 : : } 388 : : 389 : : ACPI_EXPORT_SYMBOL(acpi_put_table) 390 : : 391 : : /******************************************************************************* 392 : : * 393 : : * FUNCTION: acpi_get_table_by_index 394 : : * 395 : : * PARAMETERS: table_index - Table index 396 : : * out_table - Where the pointer to the table is returned 397 : : * 398 : : * RETURN: Status and pointer to the requested table 399 : : * 400 : : * DESCRIPTION: Obtain a table by an index into the global table list. Used 401 : : * internally also. 402 : : * 403 : : ******************************************************************************/ 404 : : acpi_status 405 : 99 : acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table) 406 : : { 407 : 99 : acpi_status status; 408 : : 409 : 99 : ACPI_FUNCTION_TRACE(acpi_get_table_by_index); 410 : : 411 : : /* Parameter validation */ 412 : : 413 [ + - ]: 99 : if (!out_table) { 414 : : return_ACPI_STATUS(AE_BAD_PARAMETER); 415 : : } 416 : : 417 : : /* 418 : : * Note that the following line is required by some OSPMs, they only 419 : : * check if the returned table is NULL instead of the returned status 420 : : * to determined if this function is succeeded. 421 : : */ 422 : 99 : *out_table = NULL; 423 : : 424 : 99 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 425 : : 426 : : /* Validate index */ 427 : : 428 [ + + ]: 99 : if (table_index >= acpi_gbl_root_table_list.current_table_count) { 429 : 11 : status = AE_BAD_PARAMETER; 430 : 11 : goto unlock_and_exit; 431 : : } 432 : : 433 : 88 : status = 434 : 88 : acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index], 435 : : out_table); 436 : : 437 : 99 : unlock_and_exit: 438 : 99 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 439 : 99 : return_ACPI_STATUS(status); 440 : : } 441 : : 442 : : ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) 443 : : 444 : : /******************************************************************************* 445 : : * 446 : : * FUNCTION: acpi_install_table_handler 447 : : * 448 : : * PARAMETERS: handler - Table event handler 449 : : * context - Value passed to the handler on each event 450 : : * 451 : : * RETURN: Status 452 : : * 453 : : * DESCRIPTION: Install a global table event handler. 454 : : * 455 : : ******************************************************************************/ 456 : : acpi_status 457 : 11 : acpi_install_table_handler(acpi_table_handler handler, void *context) 458 : : { 459 : 11 : acpi_status status; 460 : : 461 : 11 : ACPI_FUNCTION_TRACE(acpi_install_table_handler); 462 : : 463 [ + - ]: 11 : if (!handler) { 464 : : return_ACPI_STATUS(AE_BAD_PARAMETER); 465 : : } 466 : : 467 : 11 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 468 [ + - ]: 11 : if (ACPI_FAILURE(status)) { 469 : : return_ACPI_STATUS(status); 470 : : } 471 : : 472 : : /* Don't allow more than one handler */ 473 : : 474 [ - + ]: 11 : if (acpi_gbl_table_handler) { 475 : 0 : status = AE_ALREADY_EXISTS; 476 : 0 : goto cleanup; 477 : : } 478 : : 479 : : /* Install the handler */ 480 : : 481 : 11 : acpi_gbl_table_handler = handler; 482 : 11 : acpi_gbl_table_handler_context = context; 483 : : 484 : 11 : cleanup: 485 : 11 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 486 : 11 : return_ACPI_STATUS(status); 487 : : } 488 : : 489 : : ACPI_EXPORT_SYMBOL(acpi_install_table_handler) 490 : : 491 : : /******************************************************************************* 492 : : * 493 : : * FUNCTION: acpi_remove_table_handler 494 : : * 495 : : * PARAMETERS: handler - Table event handler that was installed 496 : : * previously. 497 : : * 498 : : * RETURN: Status 499 : : * 500 : : * DESCRIPTION: Remove a table event handler 501 : : * 502 : : ******************************************************************************/ 503 : 0 : acpi_status acpi_remove_table_handler(acpi_table_handler handler) 504 : : { 505 : 0 : acpi_status status; 506 : : 507 : 0 : ACPI_FUNCTION_TRACE(acpi_remove_table_handler); 508 : : 509 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 510 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 511 : : return_ACPI_STATUS(status); 512 : : } 513 : : 514 : : /* Make sure that the installed handler is the same */ 515 : : 516 [ # # # # ]: 0 : if (!handler || handler != acpi_gbl_table_handler) { 517 : 0 : status = AE_BAD_PARAMETER; 518 : 0 : goto cleanup; 519 : : } 520 : : 521 : : /* Remove the handler */ 522 : : 523 : 0 : acpi_gbl_table_handler = NULL; 524 : : 525 : 0 : cleanup: 526 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 527 : 0 : return_ACPI_STATUS(status); 528 : : } 529 : : 530 : : ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)