PageRenderTime 31ms CodeModel.GetById 7ms app.highlight 19ms RepoModel.GetById 2ms app.codeStats 0ms

/drivers/acpi/tables/tbget.c

https://bitbucket.org/evzijst/gittest
C | 493 lines | 193 code | 105 blank | 195 comment | 23 complexity | 1a31a492824e2b0b3fec944ba0c5890a MD5 | raw file
  1/******************************************************************************
  2 *
  3 * Module Name: tbget - ACPI Table get* routines
  4 *
  5 *****************************************************************************/
  6
  7/*
  8 * Copyright (C) 2000 - 2005, R. Byron Moore
  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
 45#include <acpi/acpi.h>
 46#include <acpi/actables.h>
 47
 48
 49#define _COMPONENT          ACPI_TABLES
 50	 ACPI_MODULE_NAME    ("tbget")
 51
 52
 53/*******************************************************************************
 54 *
 55 * FUNCTION:    acpi_tb_get_table
 56 *
 57 * PARAMETERS:  Address             - Address of table to retrieve.  Can be
 58 *                                    Logical or Physical
 59 *              table_info          - Where table info is returned
 60 *
 61 * RETURN:      None
 62 *
 63 * DESCRIPTION: Get entire table of unknown size.
 64 *
 65 ******************************************************************************/
 66
 67acpi_status
 68acpi_tb_get_table (
 69	struct acpi_pointer             *address,
 70	struct acpi_table_desc          *table_info)
 71{
 72	acpi_status                     status;
 73	struct acpi_table_header        header;
 74
 75
 76	ACPI_FUNCTION_TRACE ("tb_get_table");
 77
 78
 79	/*
 80	 * Get the header in order to get signature and table size
 81	 */
 82	status = acpi_tb_get_table_header (address, &header);
 83	if (ACPI_FAILURE (status)) {
 84		return_ACPI_STATUS (status);
 85	}
 86
 87	/* Get the entire table */
 88
 89	status = acpi_tb_get_table_body (address, &header, table_info);
 90	if (ACPI_FAILURE (status)) {
 91		ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n",
 92			header.length, acpi_format_exception (status)));
 93		return_ACPI_STATUS (status);
 94	}
 95
 96	return_ACPI_STATUS (AE_OK);
 97}
 98
 99
100/*******************************************************************************
101 *
102 * FUNCTION:    acpi_tb_get_table_header
103 *
104 * PARAMETERS:  Address             - Address of table to retrieve.  Can be
105 *                                    Logical or Physical
106 *              return_header       - Where the table header is returned
107 *
108 * RETURN:      Status
109 *
110 * DESCRIPTION: Get an ACPI table header.  Works in both physical or virtual
111 *              addressing mode.  Works with both physical or logical pointers.
112 *              Table is either copied or mapped, depending on the pointer
113 *              type and mode of the processor.
114 *
115 ******************************************************************************/
116
117acpi_status
118acpi_tb_get_table_header (
119	struct acpi_pointer             *address,
120	struct acpi_table_header        *return_header)
121{
122	acpi_status                     status = AE_OK;
123	struct acpi_table_header        *header = NULL;
124
125
126	ACPI_FUNCTION_TRACE ("tb_get_table_header");
127
128
129	/*
130	 * Flags contains the current processor mode (Virtual or Physical addressing)
131	 * The pointer_type is either Logical or Physical
132	 */
133	switch (address->pointer_type) {
134	case ACPI_PHYSMODE_PHYSPTR:
135	case ACPI_LOGMODE_LOGPTR:
136
137		/* Pointer matches processor mode, copy the header */
138
139		ACPI_MEMCPY (return_header, address->pointer.logical, sizeof (struct acpi_table_header));
140		break;
141
142
143	case ACPI_LOGMODE_PHYSPTR:
144
145		/* Create a logical address for the physical pointer*/
146
147		status = acpi_os_map_memory (address->pointer.physical, sizeof (struct acpi_table_header),
148				  (void *) &header);
149		if (ACPI_FAILURE (status)) {
150			ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n",
151				ACPI_FORMAT_UINT64 (address->pointer.physical),
152				sizeof (struct acpi_table_header)));
153			return_ACPI_STATUS (status);
154		}
155
156		/* Copy header and delete mapping */
157
158		ACPI_MEMCPY (return_header, header, sizeof (struct acpi_table_header));
159		acpi_os_unmap_memory (header, sizeof (struct acpi_table_header));
160		break;
161
162
163	default:
164
165		ACPI_REPORT_ERROR (("Invalid address flags %X\n",
166			address->pointer_type));
167		return_ACPI_STATUS (AE_BAD_PARAMETER);
168	}
169
170	ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
171		return_header->signature));
172
173	return_ACPI_STATUS (AE_OK);
174}
175
176
177/*******************************************************************************
178 *
179 * FUNCTION:    acpi_tb_get_table_body
180 *
181 * PARAMETERS:  Address             - Address of table to retrieve.  Can be
182 *                                    Logical or Physical
183 *              Header              - Header of the table to retrieve
184 *              table_info          - Where the table info is returned
185 *
186 * RETURN:      Status
187 *
188 * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to
189 *              replace the table with a newer version (table override.)
190 *              Works in both physical or virtual
191 *              addressing mode.  Works with both physical or logical pointers.
192 *              Table is either copied or mapped, depending on the pointer
193 *              type and mode of the processor.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_tb_get_table_body (
199	struct acpi_pointer             *address,
200	struct acpi_table_header        *header,
201	struct acpi_table_desc          *table_info)
202{
203	acpi_status                     status;
204
205
206	ACPI_FUNCTION_TRACE ("tb_get_table_body");
207
208
209	if (!table_info || !address) {
210		return_ACPI_STATUS (AE_BAD_PARAMETER);
211	}
212
213	/*
214	 * Attempt table override.
215	 */
216	status = acpi_tb_table_override (header, table_info);
217	if (ACPI_SUCCESS (status)) {
218		/* Table was overridden by the host OS */
219
220		return_ACPI_STATUS (status);
221	}
222
223	/* No override, get the original table */
224
225	status = acpi_tb_get_this_table (address, header, table_info);
226	return_ACPI_STATUS (status);
227}
228
229
230/*******************************************************************************
231 *
232 * FUNCTION:    acpi_tb_table_override
233 *
234 * PARAMETERS:  Header              - Pointer to table header
235 *              table_info          - Return info if table is overridden
236 *
237 * RETURN:      None
238 *
239 * DESCRIPTION: Attempts override of current table with a new one if provided
240 *              by the host OS.
241 *
242 ******************************************************************************/
243
244acpi_status
245acpi_tb_table_override (
246	struct acpi_table_header        *header,
247	struct acpi_table_desc          *table_info)
248{
249	struct acpi_table_header        *new_table;
250	acpi_status                     status;
251	struct acpi_pointer             address;
252
253
254	ACPI_FUNCTION_TRACE ("tb_table_override");
255
256
257	/*
258	 * The OSL will examine the header and decide whether to override this
259	 * table.  If it decides to override, a table will be returned in new_table,
260	 * which we will then copy.
261	 */
262	status = acpi_os_table_override (header, &new_table);
263	if (ACPI_FAILURE (status)) {
264		/* Some severe error from the OSL, but we basically ignore it */
265
266		ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n",
267			acpi_format_exception (status)));
268		return_ACPI_STATUS (status);
269	}
270
271	if (!new_table) {
272		/* No table override */
273
274		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
275	}
276
277	/*
278	 * We have a new table to override the old one.  Get a copy of
279	 * the new one.  We know that the new table has a logical pointer.
280	 */
281	address.pointer_type    = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
282	address.pointer.logical = new_table;
283
284	status = acpi_tb_get_this_table (&address, new_table, table_info);
285	if (ACPI_FAILURE (status)) {
286		ACPI_REPORT_ERROR (("Could not copy override ACPI table, %s\n",
287			acpi_format_exception (status)));
288		return_ACPI_STATUS (status);
289	}
290
291	/* Copy the table info */
292
293	ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n",
294		table_info->pointer->signature));
295
296	return_ACPI_STATUS (AE_OK);
297}
298
299
300/*******************************************************************************
301 *
302 * FUNCTION:    acpi_tb_get_this_table
303 *
304 * PARAMETERS:  Address             - Address of table to retrieve.  Can be
305 *                                    Logical or Physical
306 *              Header              - Header of the table to retrieve
307 *              table_info          - Where the table info is returned
308 *
309 * RETURN:      Status
310 *
311 * DESCRIPTION: Get an entire ACPI table.  Works in both physical or virtual
312 *              addressing mode.  Works with both physical or logical pointers.
313 *              Table is either copied or mapped, depending on the pointer
314 *              type and mode of the processor.
315 *
316 ******************************************************************************/
317
318acpi_status
319acpi_tb_get_this_table (
320	struct acpi_pointer             *address,
321	struct acpi_table_header        *header,
322	struct acpi_table_desc          *table_info)
323{
324	struct acpi_table_header        *full_table = NULL;
325	u8                              allocation;
326	acpi_status                     status = AE_OK;
327
328
329	ACPI_FUNCTION_TRACE ("tb_get_this_table");
330
331
332	/*
333	 * Flags contains the current processor mode (Virtual or Physical addressing)
334	 * The pointer_type is either Logical or Physical
335	 */
336	switch (address->pointer_type) {
337	case ACPI_PHYSMODE_PHYSPTR:
338	case ACPI_LOGMODE_LOGPTR:
339
340		/* Pointer matches processor mode, copy the table to a new buffer */
341
342		full_table = ACPI_MEM_ALLOCATE (header->length);
343		if (!full_table) {
344			ACPI_REPORT_ERROR (("Could not allocate table memory for [%4.4s] length %X\n",
345				header->signature, header->length));
346			return_ACPI_STATUS (AE_NO_MEMORY);
347		}
348
349		/* Copy the entire table (including header) to the local buffer */
350
351		ACPI_MEMCPY (full_table, address->pointer.logical, header->length);
352
353		/* Save allocation type */
354
355		allocation = ACPI_MEM_ALLOCATED;
356		break;
357
358
359	case ACPI_LOGMODE_PHYSPTR:
360
361		/*
362		 * Just map the table's physical memory
363		 * into our address space.
364		 */
365		status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length,
366				  (void *) &full_table);
367		if (ACPI_FAILURE (status)) {
368			ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
369				header->signature,
370				ACPI_FORMAT_UINT64 (address->pointer.physical), header->length));
371			return (status);
372		}
373
374		/* Save allocation type */
375
376		allocation = ACPI_MEM_MAPPED;
377		break;
378
379
380	default:
381
382		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n",
383			address->pointer_type));
384		return_ACPI_STATUS (AE_BAD_PARAMETER);
385	}
386
387	/*
388	 * Validate checksum for _most_ tables,
389	 * even the ones whose signature we don't recognize
390	 */
391	if (table_info->type != ACPI_TABLE_FACS) {
392		status = acpi_tb_verify_table_checksum (full_table);
393
394#if (!ACPI_CHECKSUM_ABORT)
395		if (ACPI_FAILURE (status)) {
396			/* Ignore the error if configuration says so */
397
398			status = AE_OK;
399		}
400#endif
401	}
402
403	/* Return values */
404
405	table_info->pointer     = full_table;
406	table_info->length      = (acpi_size) header->length;
407	table_info->allocation  = allocation;
408
409	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
410		"Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
411		full_table->signature,
412		ACPI_FORMAT_UINT64 (address->pointer.physical), full_table));
413
414	return_ACPI_STATUS (status);
415}
416
417
418/*******************************************************************************
419 *
420 * FUNCTION:    acpi_tb_get_table_ptr
421 *
422 * PARAMETERS:  table_type      - one of the defined table types
423 *              Instance        - Which table of this type
424 *              table_ptr_loc   - pointer to location to place the pointer for
425 *                                return
426 *
427 * RETURN:      Status
428 *
429 * DESCRIPTION: This function is called to get the pointer to an ACPI table.
430 *
431 ******************************************************************************/
432
433acpi_status
434acpi_tb_get_table_ptr (
435	acpi_table_type                 table_type,
436	u32                             instance,
437	struct acpi_table_header        **table_ptr_loc)
438{
439	struct acpi_table_desc          *table_desc;
440	u32                             i;
441
442
443	ACPI_FUNCTION_TRACE ("tb_get_table_ptr");
444
445
446	if (!acpi_gbl_DSDT) {
447		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
448	}
449
450	if (table_type > ACPI_TABLE_MAX) {
451		return_ACPI_STATUS (AE_BAD_PARAMETER);
452	}
453
454	/*
455	 * For all table types (Single/Multiple), the first
456	 * instance is always in the list head.
457	 */
458	if (instance == 1) {
459		/* Get the first */
460
461		*table_ptr_loc = NULL;
462		if (acpi_gbl_table_lists[table_type].next) {
463			*table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer;
464		}
465		return_ACPI_STATUS (AE_OK);
466	}
467
468	/*
469	 * Check for instance out of range
470	 */
471	if (instance > acpi_gbl_table_lists[table_type].count) {
472		return_ACPI_STATUS (AE_NOT_EXIST);
473	}
474
475	/* Walk the list to get the desired table
476	 * Since the if (Instance == 1) check above checked for the
477	 * first table, setting table_desc equal to the .Next member
478	 * is actually pointing to the second table.  Therefore, we
479	 * need to walk from the 2nd table until we reach the Instance
480	 * that the user is looking for and return its table pointer.
481	 */
482	table_desc = acpi_gbl_table_lists[table_type].next;
483	for (i = 2; i < instance; i++) {
484		table_desc = table_desc->next;
485	}
486
487	/* We are now pointing to the requested table's descriptor */
488
489	*table_ptr_loc = table_desc->pointer;
490
491	return_ACPI_STATUS (AE_OK);
492}
493