xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
1 /******************************************************************************
2  *
3  * Module Name: tbinstal - ACPI table installation and removal
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2008, Intel Corp.
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 
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "actables.h"
48 
49 #define _COMPONENT          ACPI_TABLES
50 ACPI_MODULE_NAME("tbinstal")
51 
52 /******************************************************************************
53  *
54  * FUNCTION:    acpi_tb_verify_table
55  *
56  * PARAMETERS:  table_desc          - table
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: this function is called to verify and map table
61  *
62  *****************************************************************************/
63 acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
64 {
65 	acpi_status status = AE_OK;
66 
67 	ACPI_FUNCTION_TRACE(tb_verify_table);
68 
69 	/* Map the table if necessary */
70 
71 	if (!table_desc->pointer) {
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 	}
82 
83 	/* FACS is the odd table, has no standard ACPI header and no checksum */
84 
85 	if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
86 
87 		/* Always calculate checksum, ignore bad checksum if requested */
88 
89 		status =
90 		    acpi_tb_verify_checksum(table_desc->pointer,
91 					    table_desc->length);
92 	}
93 
94 	return_ACPI_STATUS(status);
95 }
96 
97 /*******************************************************************************
98  *
99  * FUNCTION:    acpi_tb_add_table
100  *
101  * PARAMETERS:  table_desc          - Table descriptor
102  *              table_index         - Where the table index is returned
103  *
104  * RETURN:      Status
105  *
106  * DESCRIPTION: This function is called to add the ACPI table
107  *
108  ******************************************************************************/
109 
110 acpi_status
111 acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
112 {
113 	u32 i;
114 	acpi_status status = AE_OK;
115 
116 	ACPI_FUNCTION_TRACE(tb_add_table);
117 
118 	if (!table_desc->pointer) {
119 		status = acpi_tb_verify_table(table_desc);
120 		if (ACPI_FAILURE(status) || !table_desc->pointer) {
121 			return_ACPI_STATUS(status);
122 		}
123 	}
124 
125 	/*
126 	 * Originally, we checked the table signature for "SSDT" or "PSDT" here.
127 	 * Next, we added support for OEMx tables, signature "OEM".
128 	 * Valid tables were encountered with a null signature, so we've just
129 	 * given up on validating the signature, since it seems to be a waste
130 	 * of code. The original code was removed (05/2008).
131 	 */
132 
133 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
134 
135 	/* Check if table is already registered */
136 
137 	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
138 		if (!acpi_gbl_root_table_list.tables[i].pointer) {
139 			status =
140 			    acpi_tb_verify_table(&acpi_gbl_root_table_list.
141 						 tables[i]);
142 			if (ACPI_FAILURE(status)
143 			    || !acpi_gbl_root_table_list.tables[i].pointer) {
144 				continue;
145 			}
146 		}
147 
148 		/*
149 		 * Check for a table match on the entire table length,
150 		 * not just the header.
151 		 */
152 		if (table_desc->length !=
153 		    acpi_gbl_root_table_list.tables[i].length) {
154 			continue;
155 		}
156 
157 		if (ACPI_MEMCMP(table_desc->pointer,
158 				acpi_gbl_root_table_list.tables[i].pointer,
159 				acpi_gbl_root_table_list.tables[i].length)) {
160 			continue;
161 		}
162 
163 		/*
164 		 * Note: the current mechanism does not unregister a table if it is
165 		 * dynamically unloaded. The related namespace entries are deleted,
166 		 * but the table remains in the root table list.
167 		 *
168 		 * The assumption here is that the number of different tables that
169 		 * will be loaded is actually small, and there is minimal overhead
170 		 * in just keeping the table in case it is needed again.
171 		 *
172 		 * If this assumption changes in the future (perhaps on large
173 		 * machines with many table load/unload operations), tables will
174 		 * need to be unregistered when they are unloaded, and slots in the
175 		 * root table list should be reused when empty.
176 		 */
177 
178 		/*
179 		 * Table is already registered.
180 		 * We can delete the table that was passed as a parameter.
181 		 */
182 		acpi_tb_delete_table(table_desc);
183 		*table_index = i;
184 
185 		if (acpi_gbl_root_table_list.tables[i].
186 		    flags & ACPI_TABLE_IS_LOADED) {
187 
188 			/* Table is still loaded, this is an error */
189 
190 			status = AE_ALREADY_EXISTS;
191 			goto release;
192 		} else {
193 			/* Table was unloaded, allow it to be reloaded */
194 
195 			table_desc->pointer =
196 			    acpi_gbl_root_table_list.tables[i].pointer;
197 			table_desc->address =
198 			    acpi_gbl_root_table_list.tables[i].address;
199 			status = AE_OK;
200 			goto print_header;
201 		}
202 	}
203 
204 	/* Add the table to the global root table list */
205 
206 	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
207 				     table_desc->length, table_desc->flags,
208 				     table_index);
209 	if (ACPI_FAILURE(status)) {
210 		goto release;
211 	}
212 
213       print_header:
214 	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
215 
216       release:
217 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
218 	return_ACPI_STATUS(status);
219 }
220 
221 /*******************************************************************************
222  *
223  * FUNCTION:    acpi_tb_resize_root_table_list
224  *
225  * PARAMETERS:  None
226  *
227  * RETURN:      Status
228  *
229  * DESCRIPTION: Expand the size of global table array
230  *
231  ******************************************************************************/
232 
233 acpi_status acpi_tb_resize_root_table_list(void)
234 {
235 	struct acpi_table_desc *tables;
236 
237 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
238 
239 	/* allow_resize flag is a parameter to acpi_initialize_tables */
240 
241 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
242 		ACPI_ERROR((AE_INFO,
243 			    "Resize of Root Table Array is not allowed"));
244 		return_ACPI_STATUS(AE_SUPPORT);
245 	}
246 
247 	/* Increase the Table Array size */
248 
249 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
250 				       size + ACPI_ROOT_TABLE_SIZE_INCREMENT)
251 				      * sizeof(struct acpi_table_desc));
252 	if (!tables) {
253 		ACPI_ERROR((AE_INFO,
254 			    "Could not allocate new root table array"));
255 		return_ACPI_STATUS(AE_NO_MEMORY);
256 	}
257 
258 	/* Copy and free the previous table array */
259 
260 	if (acpi_gbl_root_table_list.tables) {
261 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
262 			    (acpi_size) acpi_gbl_root_table_list.size *
263 			    sizeof(struct acpi_table_desc));
264 
265 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
266 			ACPI_FREE(acpi_gbl_root_table_list.tables);
267 		}
268 	}
269 
270 	acpi_gbl_root_table_list.tables = tables;
271 	acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
272 	acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
273 
274 	return_ACPI_STATUS(AE_OK);
275 }
276 
277 /*******************************************************************************
278  *
279  * FUNCTION:    acpi_tb_store_table
280  *
281  * PARAMETERS:  Address             - Table address
282  *              Table               - Table header
283  *              Length              - Table length
284  *              Flags               - flags
285  *
286  * RETURN:      Status and table index.
287  *
288  * DESCRIPTION: Add an ACPI table to the global table list
289  *
290  ******************************************************************************/
291 
292 acpi_status
293 acpi_tb_store_table(acpi_physical_address address,
294 		    struct acpi_table_header *table,
295 		    u32 length, u8 flags, u32 *table_index)
296 {
297 	acpi_status status = AE_OK;
298 
299 	/* Ensure that there is room for the table in the Root Table List */
300 
301 	if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
302 		status = acpi_tb_resize_root_table_list();
303 		if (ACPI_FAILURE(status)) {
304 			return (status);
305 		}
306 	}
307 
308 	/* Initialize added table */
309 
310 	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
311 	    address = address;
312 	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
313 	    pointer = table;
314 	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
315 	    length;
316 	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
317 	    owner_id = 0;
318 	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
319 	    flags;
320 
321 	ACPI_MOVE_32_TO_32(&
322 			   (acpi_gbl_root_table_list.
323 			    tables[acpi_gbl_root_table_list.count].signature),
324 			   table->signature);
325 
326 	*table_index = acpi_gbl_root_table_list.count;
327 	acpi_gbl_root_table_list.count++;
328 	return (status);
329 }
330 
331 /*******************************************************************************
332  *
333  * FUNCTION:    acpi_tb_delete_table
334  *
335  * PARAMETERS:  table_index         - Table index
336  *
337  * RETURN:      None
338  *
339  * DESCRIPTION: Delete one internal ACPI table
340  *
341  ******************************************************************************/
342 
343 void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
344 {
345 	/* Table must be mapped or allocated */
346 	if (!table_desc->pointer) {
347 		return;
348 	}
349 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
350 	case ACPI_TABLE_ORIGIN_MAPPED:
351 		acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
352 		break;
353 	case ACPI_TABLE_ORIGIN_ALLOCATED:
354 		ACPI_FREE(table_desc->pointer);
355 		break;
356 	default:;
357 	}
358 
359 	table_desc->pointer = NULL;
360 }
361 
362 /*******************************************************************************
363  *
364  * FUNCTION:    acpi_tb_terminate
365  *
366  * PARAMETERS:  None
367  *
368  * RETURN:      None
369  *
370  * DESCRIPTION: Delete all internal ACPI tables
371  *
372  ******************************************************************************/
373 
374 void acpi_tb_terminate(void)
375 {
376 	u32 i;
377 
378 	ACPI_FUNCTION_TRACE(tb_terminate);
379 
380 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
381 
382 	/* Delete the individual tables */
383 
384 	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
385 		acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
386 	}
387 
388 	/*
389 	 * Delete the root table array if allocated locally. Array cannot be
390 	 * mapped, so we don't need to check for that flag.
391 	 */
392 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
393 		ACPI_FREE(acpi_gbl_root_table_list.tables);
394 	}
395 
396 	acpi_gbl_root_table_list.tables = NULL;
397 	acpi_gbl_root_table_list.flags = 0;
398 	acpi_gbl_root_table_list.count = 0;
399 
400 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
401 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
402 }
403 
404 /*******************************************************************************
405  *
406  * FUNCTION:    acpi_tb_delete_namespace_by_owner
407  *
408  * PARAMETERS:  table_index         - Table index
409  *
410  * RETURN:      None
411  *
412  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
413  *
414  ******************************************************************************/
415 
416 void acpi_tb_delete_namespace_by_owner(u32 table_index)
417 {
418 	acpi_owner_id owner_id;
419 
420 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
421 	if (table_index < acpi_gbl_root_table_list.count) {
422 		owner_id =
423 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
424 	} else {
425 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
426 		return;
427 	}
428 
429 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
430 	acpi_ns_delete_namespace_by_owner(owner_id);
431 }
432 
433 /*******************************************************************************
434  *
435  * FUNCTION:    acpi_tb_allocate_owner_id
436  *
437  * PARAMETERS:  table_index         - Table index
438  *
439  * RETURN:      Status
440  *
441  * DESCRIPTION: Allocates owner_id in table_desc
442  *
443  ******************************************************************************/
444 
445 acpi_status acpi_tb_allocate_owner_id(u32 table_index)
446 {
447 	acpi_status status = AE_BAD_PARAMETER;
448 
449 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
450 
451 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
452 	if (table_index < acpi_gbl_root_table_list.count) {
453 		status = acpi_ut_allocate_owner_id
454 		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
455 	}
456 
457 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
458 	return_ACPI_STATUS(status);
459 }
460 
461 /*******************************************************************************
462  *
463  * FUNCTION:    acpi_tb_release_owner_id
464  *
465  * PARAMETERS:  table_index         - Table index
466  *
467  * RETURN:      Status
468  *
469  * DESCRIPTION: Releases owner_id in table_desc
470  *
471  ******************************************************************************/
472 
473 acpi_status acpi_tb_release_owner_id(u32 table_index)
474 {
475 	acpi_status status = AE_BAD_PARAMETER;
476 
477 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
478 
479 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
480 	if (table_index < acpi_gbl_root_table_list.count) {
481 		acpi_ut_release_owner_id(&
482 					 (acpi_gbl_root_table_list.
483 					  tables[table_index].owner_id));
484 		status = AE_OK;
485 	}
486 
487 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
488 	return_ACPI_STATUS(status);
489 }
490 
491 /*******************************************************************************
492  *
493  * FUNCTION:    acpi_tb_get_owner_id
494  *
495  * PARAMETERS:  table_index         - Table index
496  *              owner_id            - Where the table owner_id is returned
497  *
498  * RETURN:      Status
499  *
500  * DESCRIPTION: returns owner_id for the ACPI table
501  *
502  ******************************************************************************/
503 
504 acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
505 {
506 	acpi_status status = AE_BAD_PARAMETER;
507 
508 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
509 
510 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
511 	if (table_index < acpi_gbl_root_table_list.count) {
512 		*owner_id =
513 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
514 		status = AE_OK;
515 	}
516 
517 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
518 	return_ACPI_STATUS(status);
519 }
520 
521 /*******************************************************************************
522  *
523  * FUNCTION:    acpi_tb_is_table_loaded
524  *
525  * PARAMETERS:  table_index         - Table index
526  *
527  * RETURN:      Table Loaded Flag
528  *
529  ******************************************************************************/
530 
531 u8 acpi_tb_is_table_loaded(u32 table_index)
532 {
533 	u8 is_loaded = FALSE;
534 
535 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
536 	if (table_index < acpi_gbl_root_table_list.count) {
537 		is_loaded = (u8)
538 		    (acpi_gbl_root_table_list.tables[table_index].
539 		     flags & ACPI_TABLE_IS_LOADED);
540 	}
541 
542 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
543 	return (is_loaded);
544 }
545 
546 /*******************************************************************************
547  *
548  * FUNCTION:    acpi_tb_set_table_loaded_flag
549  *
550  * PARAMETERS:  table_index         - Table index
551  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
552  *
553  * RETURN:      None
554  *
555  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
556  *
557  ******************************************************************************/
558 
559 void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
560 {
561 
562 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
563 	if (table_index < acpi_gbl_root_table_list.count) {
564 		if (is_loaded) {
565 			acpi_gbl_root_table_list.tables[table_index].flags |=
566 			    ACPI_TABLE_IS_LOADED;
567 		} else {
568 			acpi_gbl_root_table_list.tables[table_index].flags &=
569 			    ~ACPI_TABLE_IS_LOADED;
570 		}
571 	}
572 
573 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
574 }
575