diff options
Diffstat (limited to 'drivers/acpi/tables/tbutils.c')
-rw-r--r-- | drivers/acpi/tables/tbutils.c | 513 |
1 files changed, 329 insertions, 184 deletions
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 209a401801e3..1da64b4518c0 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Module Name: tbutils - Table manipulation utilities | 3 | * Module Name: tbutils - table utilities |
4 | * | 4 | * |
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | 8 | * Copyright (C) 2000 - 2007, R. Byron Moore |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,137 +48,119 @@ | |||
48 | ACPI_MODULE_NAME("tbutils") | 48 | ACPI_MODULE_NAME("tbutils") |
49 | 49 | ||
50 | /* Local prototypes */ | 50 | /* Local prototypes */ |
51 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 51 | static acpi_physical_address |
52 | acpi_status | 52 | acpi_tb_get_root_table_entry(u8 * table_entry, |
53 | acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); | 53 | acpi_native_uint table_entry_size); |
54 | #endif | ||
55 | 54 | ||
56 | /******************************************************************************* | 55 | /******************************************************************************* |
57 | * | 56 | * |
58 | * FUNCTION: acpi_tb_is_table_installed | 57 | * FUNCTION: acpi_tb_tables_loaded |
59 | * | ||
60 | * PARAMETERS: new_table_desc - Descriptor for new table being installed | ||
61 | * | 58 | * |
62 | * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed | 59 | * PARAMETERS: None |
63 | * | 60 | * |
64 | * DESCRIPTION: Determine if an ACPI table is already installed | 61 | * RETURN: TRUE if required ACPI tables are loaded |
65 | * | 62 | * |
66 | * MUTEX: Table data structures should be locked | 63 | * DESCRIPTION: Determine if the minimum required ACPI tables are present |
64 | * (FADT, FACS, DSDT) | ||
67 | * | 65 | * |
68 | ******************************************************************************/ | 66 | ******************************************************************************/ |
69 | 67 | ||
70 | acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) | 68 | u8 acpi_tb_tables_loaded(void) |
71 | { | 69 | { |
72 | struct acpi_table_desc *table_desc; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE(tb_is_table_installed); | ||
75 | 70 | ||
76 | /* Get the list descriptor and first table descriptor */ | 71 | if (acpi_gbl_root_table_list.count >= 3) { |
77 | 72 | return (TRUE); | |
78 | table_desc = acpi_gbl_table_lists[new_table_desc->type].next; | 73 | } |
79 | 74 | ||
80 | /* Examine all installed tables of this type */ | 75 | return (FALSE); |
76 | } | ||
81 | 77 | ||
82 | while (table_desc) { | 78 | /******************************************************************************* |
83 | /* | 79 | * |
84 | * If the table lengths match, perform a full bytewise compare. This | 80 | * FUNCTION: acpi_tb_print_table_header |
85 | * means that we will allow tables with duplicate oem_table_id(s), as | 81 | * |
86 | * long as the tables are different in some way. | 82 | * PARAMETERS: Address - Table physical address |
87 | * | 83 | * Header - Table header |
88 | * Checking if the table has been loaded into the namespace means that | 84 | * |
89 | * we don't check for duplicate tables during the initial installation | 85 | * RETURN: None |
90 | * of tables within the RSDT/XSDT. | 86 | * |
91 | */ | 87 | * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. |
92 | if ((table_desc->loaded_into_namespace) && | 88 | * |
93 | (table_desc->pointer->length == | 89 | ******************************************************************************/ |
94 | new_table_desc->pointer->length) | ||
95 | && | ||
96 | (!ACPI_MEMCMP | ||
97 | (table_desc->pointer, new_table_desc->pointer, | ||
98 | new_table_desc->pointer->length))) { | ||
99 | |||
100 | /* Match: this table is already installed */ | ||
101 | |||
102 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | ||
103 | "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", | ||
104 | new_table_desc->pointer->signature, | ||
105 | new_table_desc->pointer->revision, | ||
106 | new_table_desc->pointer-> | ||
107 | oem_table_id)); | ||
108 | |||
109 | new_table_desc->owner_id = table_desc->owner_id; | ||
110 | new_table_desc->installed_desc = table_desc; | ||
111 | |||
112 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | ||
113 | } | ||
114 | 90 | ||
115 | /* Get next table on the list */ | 91 | void |
92 | acpi_tb_print_table_header(acpi_physical_address address, | ||
93 | struct acpi_table_header *header) | ||
94 | { | ||
116 | 95 | ||
117 | table_desc = table_desc->next; | 96 | if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { |
97 | |||
98 | /* FACS only has signature and length fields of common table header */ | ||
99 | |||
100 | ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", | ||
101 | header->signature, (unsigned long)address, | ||
102 | header->length)); | ||
103 | } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { | ||
104 | |||
105 | /* RSDP has no common fields */ | ||
106 | |||
107 | ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", | ||
108 | (unsigned long)address, | ||
109 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> | ||
110 | revision > | ||
111 | 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
112 | header)->length : 20, | ||
113 | ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
114 | header)->revision, | ||
115 | ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
116 | header)->oem_id)); | ||
117 | } else { | ||
118 | /* Standard ACPI table with full common header */ | ||
119 | |||
120 | ACPI_INFO((AE_INFO, | ||
121 | "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", | ||
122 | header->signature, (unsigned long)address, | ||
123 | header->length, header->revision, header->oem_id, | ||
124 | header->oem_table_id, header->oem_revision, | ||
125 | header->asl_compiler_id, | ||
126 | header->asl_compiler_revision)); | ||
118 | } | 127 | } |
119 | |||
120 | return_ACPI_STATUS(AE_OK); | ||
121 | } | 128 | } |
122 | 129 | ||
123 | /******************************************************************************* | 130 | /******************************************************************************* |
124 | * | 131 | * |
125 | * FUNCTION: acpi_tb_validate_table_header | 132 | * FUNCTION: acpi_tb_validate_checksum |
126 | * | 133 | * |
127 | * PARAMETERS: table_header - Logical pointer to the table | 134 | * PARAMETERS: Table - ACPI table to verify |
135 | * Length - Length of entire table | ||
128 | * | 136 | * |
129 | * RETURN: Status | 137 | * RETURN: Status |
130 | * | 138 | * |
131 | * DESCRIPTION: Check an ACPI table header for validity | 139 | * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns |
132 | * | 140 | * exception on bad checksum. |
133 | * NOTE: Table pointers are validated as follows: | ||
134 | * 1) Table pointer must point to valid physical memory | ||
135 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
136 | * name | ||
137 | * 3) Table must be readable for length specified in the header | ||
138 | * 4) Table checksum must be valid (with the exception of the FACS | ||
139 | * which has no checksum because it contains variable fields) | ||
140 | * | 141 | * |
141 | ******************************************************************************/ | 142 | ******************************************************************************/ |
142 | 143 | ||
143 | acpi_status | 144 | acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) |
144 | acpi_tb_validate_table_header(struct acpi_table_header *table_header) | ||
145 | { | 145 | { |
146 | acpi_name signature; | 146 | u8 checksum; |
147 | |||
148 | ACPI_FUNCTION_ENTRY(); | ||
149 | |||
150 | /* Verify that this is a valid address */ | ||
151 | |||
152 | if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { | ||
153 | ACPI_ERROR((AE_INFO, | ||
154 | "Cannot read table header at %p", table_header)); | ||
155 | |||
156 | return (AE_BAD_ADDRESS); | ||
157 | } | ||
158 | 147 | ||
159 | /* Ensure that the signature is 4 ASCII characters */ | 148 | /* Compute the checksum on the table */ |
160 | 149 | ||
161 | ACPI_MOVE_32_TO_32(&signature, table_header->signature); | 150 | checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); |
162 | if (!acpi_ut_valid_acpi_name(signature)) { | ||
163 | ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", | ||
164 | signature)); | ||
165 | 151 | ||
166 | ACPI_DUMP_BUFFER(table_header, | 152 | /* Checksum ok? (should be zero) */ |
167 | sizeof(struct acpi_table_header)); | ||
168 | return (AE_BAD_SIGNATURE); | ||
169 | } | ||
170 | 153 | ||
171 | /* Validate the table length */ | 154 | if (checksum) { |
155 | ACPI_WARNING((AE_INFO, | ||
156 | "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", | ||
157 | table->signature, table->checksum, | ||
158 | (u8) (table->checksum - checksum))); | ||
172 | 159 | ||
173 | if (table_header->length < sizeof(struct acpi_table_header)) { | 160 | #if (ACPI_CHECKSUM_ABORT) |
174 | ACPI_ERROR((AE_INFO, | ||
175 | "Invalid length 0x%X in table with signature %4.4s", | ||
176 | (u32) table_header->length, | ||
177 | ACPI_CAST_PTR(char, &signature))); | ||
178 | 161 | ||
179 | ACPI_DUMP_BUFFER(table_header, | 162 | return (AE_BAD_CHECKSUM); |
180 | sizeof(struct acpi_table_header)); | 163 | #endif |
181 | return (AE_BAD_HEADER); | ||
182 | } | 164 | } |
183 | 165 | ||
184 | return (AE_OK); | 166 | return (AE_OK); |
@@ -186,157 +168,320 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) | |||
186 | 168 | ||
187 | /******************************************************************************* | 169 | /******************************************************************************* |
188 | * | 170 | * |
189 | * FUNCTION: acpi_tb_sum_table | 171 | * FUNCTION: acpi_tb_checksum |
190 | * | 172 | * |
191 | * PARAMETERS: Buffer - Buffer to sum | 173 | * PARAMETERS: Buffer - Pointer to memory region to be checked |
192 | * Length - Size of the buffer | 174 | * Length - Length of this memory region |
193 | * | 175 | * |
194 | * RETURN: 8 bit sum of buffer | 176 | * RETURN: Checksum (u8) |
195 | * | 177 | * |
196 | * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. | 178 | * DESCRIPTION: Calculates circular checksum of memory region. |
197 | * | 179 | * |
198 | ******************************************************************************/ | 180 | ******************************************************************************/ |
199 | 181 | ||
200 | u8 acpi_tb_sum_table(void *buffer, u32 length) | 182 | u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) |
201 | { | 183 | { |
202 | acpi_native_uint i; | ||
203 | u8 sum = 0; | 184 | u8 sum = 0; |
185 | u8 *end = buffer + length; | ||
204 | 186 | ||
205 | if (!buffer || !length) { | 187 | while (buffer < end) { |
206 | return (0); | 188 | sum = (u8) (sum + *(buffer++)); |
207 | } | 189 | } |
208 | 190 | ||
209 | for (i = 0; i < length; i++) { | 191 | return sum; |
210 | sum = (u8) (sum + ((u8 *) buffer)[i]); | ||
211 | } | ||
212 | return (sum); | ||
213 | } | 192 | } |
214 | 193 | ||
215 | /******************************************************************************* | 194 | /******************************************************************************* |
216 | * | 195 | * |
217 | * FUNCTION: acpi_tb_generate_checksum | 196 | * FUNCTION: acpi_tb_install_table |
218 | * | 197 | * |
219 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 198 | * PARAMETERS: Address - Physical address of DSDT or FACS |
220 | * standard ACPI header) | 199 | * Flags - Flags |
200 | * Signature - Table signature, NULL if no need to | ||
201 | * match | ||
202 | * table_index - Index into root table array | ||
221 | * | 203 | * |
222 | * RETURN: 8 bit checksum of buffer | 204 | * RETURN: None |
223 | * | 205 | * |
224 | * DESCRIPTION: Computes an 8 bit checksum of the table. | 206 | * DESCRIPTION: Install an ACPI table into the global data structure. |
225 | * | 207 | * |
226 | ******************************************************************************/ | 208 | ******************************************************************************/ |
227 | 209 | ||
228 | u8 acpi_tb_generate_checksum(struct acpi_table_header * table) | 210 | void |
211 | acpi_tb_install_table(acpi_physical_address address, | ||
212 | u8 flags, char *signature, acpi_native_uint table_index) | ||
229 | { | 213 | { |
230 | u8 checksum; | 214 | struct acpi_table_header *table; |
215 | |||
216 | if (!address) { | ||
217 | ACPI_ERROR((AE_INFO, | ||
218 | "Null physical address for ACPI table [%s]", | ||
219 | signature)); | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | /* Map just the table header */ | ||
224 | |||
225 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
226 | if (!table) { | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | /* If a particular signature is expected, signature must match */ | ||
231 | |||
232 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { | ||
233 | ACPI_ERROR((AE_INFO, | ||
234 | "Invalid signature 0x%X for ACPI table [%s]", | ||
235 | *ACPI_CAST_PTR(u32, table->signature), signature)); | ||
236 | goto unmap_and_exit; | ||
237 | } | ||
231 | 238 | ||
232 | /* Sum the entire table as-is */ | 239 | /* Initialize the table entry */ |
233 | 240 | ||
234 | checksum = acpi_tb_sum_table(table, table->length); | 241 | acpi_gbl_root_table_list.tables[table_index].address = address; |
242 | acpi_gbl_root_table_list.tables[table_index].length = table->length; | ||
243 | acpi_gbl_root_table_list.tables[table_index].flags = flags; | ||
235 | 244 | ||
236 | /* Subtract off the existing checksum value in the table */ | 245 | ACPI_MOVE_32_TO_32(& |
246 | (acpi_gbl_root_table_list.tables[table_index]. | ||
247 | signature), table->signature); | ||
237 | 248 | ||
238 | checksum = (u8) (checksum - table->checksum); | 249 | acpi_tb_print_table_header(address, table); |
239 | 250 | ||
240 | /* Compute the final checksum */ | 251 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
241 | 252 | ||
242 | checksum = (u8) (0 - checksum); | 253 | /* Global integer width is based upon revision of the DSDT */ |
243 | return (checksum); | 254 | |
255 | acpi_ut_set_integer_width(table->revision); | ||
256 | } | ||
257 | |||
258 | unmap_and_exit: | ||
259 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
244 | } | 260 | } |
245 | 261 | ||
246 | /******************************************************************************* | 262 | /******************************************************************************* |
247 | * | 263 | * |
248 | * FUNCTION: acpi_tb_set_checksum | 264 | * FUNCTION: acpi_tb_get_root_table_entry |
249 | * | 265 | * |
250 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 266 | * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry |
251 | * standard ACPI header) | 267 | * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) |
252 | * | 268 | * |
253 | * RETURN: None. Sets the table checksum field | 269 | * RETURN: Physical address extracted from the root table |
254 | * | 270 | * |
255 | * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the | 271 | * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on |
256 | * checksum into the table header. | 272 | * both 32-bit and 64-bit platforms |
273 | * | ||
274 | * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on | ||
275 | * 64-bit platforms. | ||
257 | * | 276 | * |
258 | ******************************************************************************/ | 277 | ******************************************************************************/ |
259 | 278 | ||
260 | void acpi_tb_set_checksum(struct acpi_table_header *table) | 279 | static acpi_physical_address |
280 | acpi_tb_get_root_table_entry(u8 * table_entry, | ||
281 | acpi_native_uint table_entry_size) | ||
261 | { | 282 | { |
283 | u64 address64; | ||
284 | |||
285 | /* | ||
286 | * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): | ||
287 | * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT | ||
288 | */ | ||
289 | if (table_entry_size == sizeof(u32)) { | ||
290 | /* | ||
291 | * 32-bit platform, RSDT: Return 32-bit table entry | ||
292 | * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return | ||
293 | */ | ||
294 | return ((acpi_physical_address) | ||
295 | (*ACPI_CAST_PTR(u32, table_entry))); | ||
296 | } else { | ||
297 | /* | ||
298 | * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return | ||
299 | * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit | ||
300 | */ | ||
301 | ACPI_MOVE_64_TO_64(&address64, table_entry); | ||
262 | 302 | ||
263 | table->checksum = acpi_tb_generate_checksum(table); | 303 | #if ACPI_MACHINE_WIDTH == 32 |
304 | if (address64 > ACPI_UINT32_MAX) { | ||
305 | |||
306 | /* Will truncate 64-bit address to 32 bits, issue warning */ | ||
307 | |||
308 | ACPI_WARNING((AE_INFO, | ||
309 | "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", | ||
310 | ACPI_FORMAT_UINT64(address64))); | ||
311 | } | ||
312 | #endif | ||
313 | return ((acpi_physical_address) (address64)); | ||
314 | } | ||
264 | } | 315 | } |
265 | 316 | ||
266 | /******************************************************************************* | 317 | /******************************************************************************* |
267 | * | 318 | * |
268 | * FUNCTION: acpi_tb_verify_table_checksum | 319 | * FUNCTION: acpi_tb_parse_root_table |
320 | * | ||
321 | * PARAMETERS: Rsdp - Pointer to the RSDP | ||
322 | * Flags - Flags | ||
269 | * | 323 | * |
270 | * PARAMETERS: *table_header - ACPI table to verify | 324 | * RETURN: Status |
271 | * | 325 | * |
272 | * RETURN: 8 bit checksum of table | 326 | * DESCRIPTION: This function is called to parse the Root System Description |
327 | * Table (RSDT or XSDT) | ||
273 | * | 328 | * |
274 | * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares | 329 | * NOTE: Tables are mapped (not copied) for efficiency. The FACS must |
275 | * it to the existing checksum value. | 330 | * be mapped and cannot be copied because it contains the actual |
331 | * memory location of the ACPI Global Lock. | ||
276 | * | 332 | * |
277 | ******************************************************************************/ | 333 | ******************************************************************************/ |
278 | 334 | ||
279 | acpi_status | 335 | acpi_status __init |
280 | acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) | 336 | acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) |
281 | { | 337 | { |
282 | u8 checksum; | 338 | struct acpi_table_rsdp *rsdp; |
339 | acpi_native_uint table_entry_size; | ||
340 | acpi_native_uint i; | ||
341 | u32 table_count; | ||
342 | struct acpi_table_header *table; | ||
343 | acpi_physical_address address; | ||
344 | u32 length; | ||
345 | u8 *table_entry; | ||
346 | acpi_status status; | ||
347 | |||
348 | ACPI_FUNCTION_TRACE(tb_parse_root_table); | ||
349 | |||
350 | /* | ||
351 | * Map the entire RSDP and extract the address of the RSDT or XSDT | ||
352 | */ | ||
353 | rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); | ||
354 | if (!rsdp) { | ||
355 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
356 | } | ||
283 | 357 | ||
284 | ACPI_FUNCTION_TRACE(tb_verify_table_checksum); | 358 | acpi_tb_print_table_header(rsdp_address, |
359 | ACPI_CAST_PTR(struct acpi_table_header, | ||
360 | rsdp)); | ||
285 | 361 | ||
286 | /* Compute the checksum on the table */ | 362 | /* Differentiate between RSDT and XSDT root tables */ |
287 | 363 | ||
288 | checksum = acpi_tb_generate_checksum(table_header); | 364 | if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { |
365 | /* | ||
366 | * Root table is an XSDT (64-bit physical addresses). We must use the | ||
367 | * XSDT if the revision is > 1 and the XSDT pointer is present, as per | ||
368 | * the ACPI specification. | ||
369 | */ | ||
370 | address = (acpi_physical_address) rsdp->xsdt_physical_address; | ||
371 | table_entry_size = sizeof(u64); | ||
372 | } else { | ||
373 | /* Root table is an RSDT (32-bit physical addresses) */ | ||
289 | 374 | ||
290 | /* Checksum ok? */ | 375 | address = (acpi_physical_address) rsdp->rsdt_physical_address; |
376 | table_entry_size = sizeof(u32); | ||
377 | } | ||
291 | 378 | ||
292 | if (checksum == table_header->checksum) { | 379 | /* |
293 | return_ACPI_STATUS(AE_OK); | 380 | * It is not possible to map more than one entry in some environments, |
381 | * so unmap the RSDP here before mapping other tables | ||
382 | */ | ||
383 | acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); | ||
384 | |||
385 | /* Map the RSDT/XSDT table header to get the full table length */ | ||
386 | |||
387 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
388 | if (!table) { | ||
389 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
294 | } | 390 | } |
295 | 391 | ||
296 | ACPI_WARNING((AE_INFO, | 392 | acpi_tb_print_table_header(address, table); |
297 | "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", | ||
298 | table_header->signature, table_header->checksum, | ||
299 | checksum)); | ||
300 | 393 | ||
301 | return_ACPI_STATUS(AE_BAD_CHECKSUM); | 394 | /* Get the length of the full table, verify length and map entire table */ |
302 | } | ||
303 | 395 | ||
304 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 396 | length = table->length; |
305 | /******************************************************************************* | 397 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); |
306 | * | ||
307 | * FUNCTION: acpi_tb_handle_to_object | ||
308 | * | ||
309 | * PARAMETERS: table_id - Id for which the function is searching | ||
310 | * table_desc - Pointer to return the matching table | ||
311 | * descriptor. | ||
312 | * | ||
313 | * RETURN: Search the tables to find one with a matching table_id and | ||
314 | * return a pointer to that table descriptor. | ||
315 | * | ||
316 | ******************************************************************************/ | ||
317 | 398 | ||
318 | acpi_status | 399 | if (length < sizeof(struct acpi_table_header)) { |
319 | acpi_tb_handle_to_object(u16 table_id, | 400 | ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", |
320 | struct acpi_table_desc **return_table_desc) | 401 | length)); |
321 | { | 402 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); |
322 | u32 i; | 403 | } |
323 | struct acpi_table_desc *table_desc; | ||
324 | 404 | ||
325 | ACPI_FUNCTION_NAME(tb_handle_to_object); | 405 | table = acpi_os_map_memory(address, length); |
406 | if (!table) { | ||
407 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
408 | } | ||
409 | |||
410 | /* Validate the root table checksum */ | ||
411 | |||
412 | status = acpi_tb_verify_checksum(table, length); | ||
413 | if (ACPI_FAILURE(status)) { | ||
414 | acpi_os_unmap_memory(table, length); | ||
415 | return_ACPI_STATUS(status); | ||
416 | } | ||
326 | 417 | ||
327 | for (i = 0; i < ACPI_TABLE_MAX; i++) { | 418 | /* Calculate the number of tables described in the root table */ |
328 | table_desc = acpi_gbl_table_lists[i].next; | 419 | |
329 | while (table_desc) { | 420 | table_count = |
330 | if (table_desc->table_id == table_id) { | 421 | (u32) ((table->length - |
331 | *return_table_desc = table_desc; | 422 | sizeof(struct acpi_table_header)) / table_entry_size); |
332 | return (AE_OK); | 423 | |
424 | /* | ||
425 | * First two entries in the table array are reserved for the DSDT and FACS, | ||
426 | * which are not actually present in the RSDT/XSDT - they come from the FADT | ||
427 | */ | ||
428 | table_entry = | ||
429 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); | ||
430 | acpi_gbl_root_table_list.count = 2; | ||
431 | |||
432 | /* | ||
433 | * Initialize the root table array from the RSDT/XSDT | ||
434 | */ | ||
435 | for (i = 0; i < table_count; i++) { | ||
436 | if (acpi_gbl_root_table_list.count >= | ||
437 | acpi_gbl_root_table_list.size) { | ||
438 | |||
439 | /* There is no more room in the root table array, attempt resize */ | ||
440 | |||
441 | status = acpi_tb_resize_root_table_list(); | ||
442 | if (ACPI_FAILURE(status)) { | ||
443 | ACPI_WARNING((AE_INFO, | ||
444 | "Truncating %u table entries!", | ||
445 | (unsigned) | ||
446 | (acpi_gbl_root_table_list.size - | ||
447 | acpi_gbl_root_table_list. | ||
448 | count))); | ||
449 | break; | ||
333 | } | 450 | } |
451 | } | ||
452 | |||
453 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ | ||
334 | 454 | ||
335 | table_desc = table_desc->next; | 455 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. |
456 | address = | ||
457 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); | ||
458 | |||
459 | table_entry += table_entry_size; | ||
460 | acpi_gbl_root_table_list.count++; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * It is not possible to map more than one entry in some environments, | ||
465 | * so unmap the root table here before mapping other tables | ||
466 | */ | ||
467 | acpi_os_unmap_memory(table, length); | ||
468 | |||
469 | /* | ||
470 | * Complete the initialization of the root table array by examining | ||
471 | * the header of each table | ||
472 | */ | ||
473 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { | ||
474 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. | ||
475 | address, flags, NULL, i); | ||
476 | |||
477 | /* Special case for FADT - get the DSDT and FACS */ | ||
478 | |||
479 | if (ACPI_COMPARE_NAME | ||
480 | (&acpi_gbl_root_table_list.tables[i].signature, | ||
481 | ACPI_SIG_FADT)) { | ||
482 | acpi_tb_parse_fadt(i, flags); | ||
336 | } | 483 | } |
337 | } | 484 | } |
338 | 485 | ||
339 | ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); | 486 | return_ACPI_STATUS(AE_OK); |
340 | return (AE_BAD_PARAMETER); | ||
341 | } | 487 | } |
342 | #endif | ||