diff options
Diffstat (limited to 'drivers/acpi/tables/tbutils.c')
-rw-r--r-- | drivers/acpi/tables/tbutils.c | 600 |
1 files changed, 406 insertions, 194 deletions
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 209a401801e3..3620ac5f8681 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Module Name: tbutils - Table manipulation utilities | 3 | * Module Name: tbutils - table utilities |
4 | * | 4 | * |
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
@@ -48,295 +48,507 @@ | |||
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 void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags); |
52 | acpi_status | 52 | |
53 | acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); | 53 | static void inline |
54 | #endif | 54 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, |
55 | u8 bit_width, acpi_physical_address address); | ||
55 | 56 | ||
56 | /******************************************************************************* | 57 | /******************************************************************************* |
57 | * | 58 | * |
58 | * FUNCTION: acpi_tb_is_table_installed | 59 | * FUNCTION: acpi_tb_print_table_header |
59 | * | 60 | * |
60 | * PARAMETERS: new_table_desc - Descriptor for new table being installed | 61 | * PARAMETERS: Address - Table physical address |
62 | * Header - Table header | ||
61 | * | 63 | * |
62 | * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed | 64 | * RETURN: None |
63 | * | 65 | * |
64 | * DESCRIPTION: Determine if an ACPI table is already installed | 66 | * DESCRIPTION: Print an ACPI table header |
65 | * | ||
66 | * MUTEX: Table data structures should be locked | ||
67 | * | 67 | * |
68 | ******************************************************************************/ | 68 | ******************************************************************************/ |
69 | 69 | ||
70 | acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) | 70 | void |
71 | acpi_tb_print_table_header(acpi_physical_address address, | ||
72 | struct acpi_table_header *header) | ||
71 | { | 73 | { |
72 | struct acpi_table_desc *table_desc; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE(tb_is_table_installed); | ||
75 | |||
76 | /* Get the list descriptor and first table descriptor */ | ||
77 | |||
78 | table_desc = acpi_gbl_table_lists[new_table_desc->type].next; | ||
79 | |||
80 | /* Examine all installed tables of this type */ | ||
81 | |||
82 | while (table_desc) { | ||
83 | /* | ||
84 | * If the table lengths match, perform a full bytewise compare. This | ||
85 | * means that we will allow tables with duplicate oem_table_id(s), as | ||
86 | * long as the tables are different in some way. | ||
87 | * | ||
88 | * Checking if the table has been loaded into the namespace means that | ||
89 | * we don't check for duplicate tables during the initial installation | ||
90 | * of tables within the RSDT/XSDT. | ||
91 | */ | ||
92 | if ((table_desc->loaded_into_namespace) && | ||
93 | (table_desc->pointer->length == | ||
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 | |||
115 | /* Get next table on the list */ | ||
116 | 74 | ||
117 | table_desc = table_desc->next; | 75 | ACPI_INFO((AE_INFO, |
118 | } | 76 | "%4.4s @ 0x%p Length 0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)", |
119 | 77 | header->signature, ACPI_CAST_PTR(void, address), | |
120 | return_ACPI_STATUS(AE_OK); | 78 | header->length, header->revision, header->oem_id, |
79 | header->oem_table_id, header->oem_revision, | ||
80 | header->asl_compiler_id, header->asl_compiler_revision)); | ||
121 | } | 81 | } |
122 | 82 | ||
123 | /******************************************************************************* | 83 | /******************************************************************************* |
124 | * | 84 | * |
125 | * FUNCTION: acpi_tb_validate_table_header | 85 | * FUNCTION: acpi_tb_init_generic_address |
126 | * | ||
127 | * PARAMETERS: table_header - Logical pointer to the table | ||
128 | * | 86 | * |
129 | * RETURN: Status | 87 | * PARAMETERS: new_gas_struct - GAS struct to be initialized |
88 | * bit_width - Width of this register | ||
89 | * Address - Address of the register | ||
130 | * | 90 | * |
131 | * DESCRIPTION: Check an ACPI table header for validity | 91 | * RETURN: None |
132 | * | 92 | * |
133 | * NOTE: Table pointers are validated as follows: | 93 | * DESCRIPTION: Initialize a GAS structure. |
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 | * | 94 | * |
141 | ******************************************************************************/ | 95 | ******************************************************************************/ |
142 | 96 | ||
143 | acpi_status | 97 | static void inline |
144 | acpi_tb_validate_table_header(struct acpi_table_header *table_header) | 98 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, |
99 | u8 bit_width, acpi_physical_address address) | ||
145 | { | 100 | { |
146 | acpi_name signature; | ||
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 | |||
159 | /* Ensure that the signature is 4 ASCII characters */ | ||
160 | |||
161 | ACPI_MOVE_32_TO_32(&signature, table_header->signature); | ||
162 | if (!acpi_ut_valid_acpi_name(signature)) { | ||
163 | ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", | ||
164 | signature)); | ||
165 | 101 | ||
166 | ACPI_DUMP_BUFFER(table_header, | 102 | ACPI_STORE_ADDRESS(new_gas_struct->address, address); |
167 | sizeof(struct acpi_table_header)); | 103 | new_gas_struct->space_id = ACPI_ADR_SPACE_SYSTEM_IO; |
168 | return (AE_BAD_SIGNATURE); | 104 | new_gas_struct->bit_width = bit_width; |
169 | } | 105 | new_gas_struct->bit_offset = 0; |
170 | 106 | new_gas_struct->access_width = 0; | |
171 | /* Validate the table length */ | ||
172 | |||
173 | if (table_header->length < sizeof(struct acpi_table_header)) { | ||
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 | |||
179 | ACPI_DUMP_BUFFER(table_header, | ||
180 | sizeof(struct acpi_table_header)); | ||
181 | return (AE_BAD_HEADER); | ||
182 | } | ||
183 | |||
184 | return (AE_OK); | ||
185 | } | 107 | } |
186 | 108 | ||
187 | /******************************************************************************* | 109 | /******************************************************************************* |
188 | * | 110 | * |
189 | * FUNCTION: acpi_tb_sum_table | 111 | * FUNCTION: acpi_tb_checksum |
190 | * | 112 | * |
191 | * PARAMETERS: Buffer - Buffer to sum | 113 | * PARAMETERS: Buffer - Pointer to memory region to be checked |
192 | * Length - Size of the buffer | 114 | * Length - Length of this memory region |
193 | * | 115 | * |
194 | * RETURN: 8 bit sum of buffer | 116 | * RETURN: Checksum (u8) |
195 | * | 117 | * |
196 | * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. | 118 | * DESCRIPTION: Calculates circular checksum of memory region. |
197 | * | 119 | * |
198 | ******************************************************************************/ | 120 | ******************************************************************************/ |
199 | 121 | ||
200 | u8 acpi_tb_sum_table(void *buffer, u32 length) | 122 | u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) |
201 | { | 123 | { |
202 | acpi_native_uint i; | ||
203 | u8 sum = 0; | 124 | u8 sum = 0; |
125 | u8 *end = buffer + length; | ||
204 | 126 | ||
205 | if (!buffer || !length) { | 127 | while (buffer < end) { |
206 | return (0); | 128 | sum = (u8) (sum + *(buffer++)); |
207 | } | 129 | } |
208 | 130 | ||
209 | for (i = 0; i < length; i++) { | 131 | return sum; |
210 | sum = (u8) (sum + ((u8 *) buffer)[i]); | ||
211 | } | ||
212 | return (sum); | ||
213 | } | 132 | } |
214 | 133 | ||
215 | /******************************************************************************* | 134 | /******************************************************************************* |
216 | * | 135 | * |
217 | * FUNCTION: acpi_tb_generate_checksum | 136 | * FUNCTION: acpi_tb_convert_fadt |
218 | * | 137 | * |
219 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 138 | * PARAMETERS: Fadt - FADT table to be converted |
220 | * standard ACPI header) | ||
221 | * | 139 | * |
222 | * RETURN: 8 bit checksum of buffer | 140 | * RETURN: None |
223 | * | 141 | * |
224 | * DESCRIPTION: Computes an 8 bit checksum of the table. | 142 | * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local |
143 | * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply | ||
144 | * copied to the local FADT. The ACPI CA software uses this | ||
145 | * local FADT. Thus a significant amount of special #ifdef | ||
146 | * type codeing is saved. | ||
225 | * | 147 | * |
226 | ******************************************************************************/ | 148 | ******************************************************************************/ |
227 | 149 | ||
228 | u8 acpi_tb_generate_checksum(struct acpi_table_header * table) | 150 | void acpi_tb_convert_fadt(struct acpi_table_fadt *fadt) |
229 | { | 151 | { |
230 | u8 checksum; | ||
231 | |||
232 | /* Sum the entire table as-is */ | ||
233 | 152 | ||
234 | checksum = acpi_tb_sum_table(table, table->length); | 153 | /* |
154 | * Convert table pointers to 64-bit fields | ||
155 | */ | ||
156 | if (!acpi_gbl_FADT.Xfacs) { | ||
157 | acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; | ||
158 | } | ||
235 | 159 | ||
236 | /* Subtract off the existing checksum value in the table */ | 160 | if (!acpi_gbl_FADT.Xdsdt) { |
161 | acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; | ||
162 | } | ||
237 | 163 | ||
238 | checksum = (u8) (checksum - table->checksum); | 164 | /* |
165 | * Convert the V1.0 block addresses to V2.0 GAS structures | ||
166 | */ | ||
167 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_event_block, | ||
168 | acpi_gbl_FADT.pm1_event_length, | ||
169 | (acpi_physical_address) acpi_gbl_FADT. | ||
170 | pm1a_event_block); | ||
171 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_event_block, | ||
172 | acpi_gbl_FADT.pm1_event_length, | ||
173 | (acpi_physical_address) acpi_gbl_FADT. | ||
174 | pm1b_event_block); | ||
175 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_control_block, | ||
176 | acpi_gbl_FADT.pm1_control_length, | ||
177 | (acpi_physical_address) acpi_gbl_FADT. | ||
178 | pm1a_control_block); | ||
179 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_control_block, | ||
180 | acpi_gbl_FADT.pm1_control_length, | ||
181 | (acpi_physical_address) acpi_gbl_FADT. | ||
182 | pm1b_control_block); | ||
183 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm2_control_block, | ||
184 | acpi_gbl_FADT.pm2_control_length, | ||
185 | (acpi_physical_address) acpi_gbl_FADT. | ||
186 | pm2_control_block); | ||
187 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm_timer_block, | ||
188 | acpi_gbl_FADT.pm_timer_length, | ||
189 | (acpi_physical_address) acpi_gbl_FADT. | ||
190 | pm_timer_block); | ||
191 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe0_block, 0, | ||
192 | (acpi_physical_address) acpi_gbl_FADT. | ||
193 | gpe0_block); | ||
194 | acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe1_block, 0, | ||
195 | (acpi_physical_address) acpi_gbl_FADT. | ||
196 | gpe1_block); | ||
197 | |||
198 | /* | ||
199 | * Create separate GAS structs for the PM1 Enable registers | ||
200 | */ | ||
201 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, | ||
202 | (u8) ACPI_DIV_2(acpi_gbl_FADT. | ||
203 | pm1_event_length), | ||
204 | (acpi_physical_address) | ||
205 | (acpi_gbl_FADT.xpm1a_event_block.address + | ||
206 | ACPI_DIV_2(acpi_gbl_FADT. | ||
207 | pm1_event_length))); | ||
208 | |||
209 | /* | ||
210 | * PM1B is optional; leave null if not present | ||
211 | */ | ||
212 | if (acpi_gbl_FADT.xpm1b_event_block.address) { | ||
213 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | ||
214 | (u8) ACPI_DIV_2(acpi_gbl_FADT. | ||
215 | pm1_event_length), | ||
216 | (acpi_physical_address) | ||
217 | (acpi_gbl_FADT.xpm1b_event_block. | ||
218 | address + | ||
219 | ACPI_DIV_2(acpi_gbl_FADT. | ||
220 | pm1_event_length))); | ||
221 | } | ||
239 | 222 | ||
240 | /* Compute the final checksum */ | 223 | /* Global FADT is the new common V2.0 FADT */ |
241 | 224 | ||
242 | checksum = (u8) (0 - checksum); | 225 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); |
243 | return (checksum); | ||
244 | } | 226 | } |
245 | 227 | ||
246 | /******************************************************************************* | 228 | /******************************************************************************* |
247 | * | 229 | * |
248 | * FUNCTION: acpi_tb_set_checksum | 230 | * FUNCTION: acpi_tb_parse_fadt |
249 | * | 231 | * |
250 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 232 | * PARAMETERS: Fadt - Pointer to FADT table |
251 | * standard ACPI header) | 233 | * Flags - Flags |
252 | * | 234 | * |
253 | * RETURN: None. Sets the table checksum field | 235 | * RETURN: none |
254 | * | 236 | * |
255 | * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the | 237 | * DESCRIPTION: This function is called to initialise the FADT, DSDT and FACS |
256 | * checksum into the table header. | 238 | * tables (FADT contains the addresses of the DSDT and FACS) |
257 | * | 239 | * |
258 | ******************************************************************************/ | 240 | ******************************************************************************/ |
259 | 241 | ||
260 | void acpi_tb_set_checksum(struct acpi_table_header *table) | 242 | static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags) |
261 | { | 243 | { |
244 | acpi_physical_address dsdt_address = | ||
245 | (acpi_physical_address) fadt->Xdsdt; | ||
246 | acpi_physical_address facs_address = | ||
247 | (acpi_physical_address) fadt->Xfacs; | ||
248 | struct acpi_table_header *table; | ||
249 | |||
250 | if (!dsdt_address) { | ||
251 | goto no_dsdt; | ||
252 | } | ||
253 | |||
254 | table = | ||
255 | acpi_os_map_memory(dsdt_address, sizeof(struct acpi_table_header)); | ||
256 | if (!table) { | ||
257 | goto no_dsdt; | ||
258 | } | ||
259 | |||
260 | /* Initialize the DSDT table */ | ||
261 | |||
262 | ACPI_MOVE_32_TO_32(& | ||
263 | (acpi_gbl_root_table_list. | ||
264 | tables[ACPI_TABLE_INDEX_DSDT].signature), | ||
265 | ACPI_SIG_DSDT); | ||
266 | |||
267 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].address = | ||
268 | dsdt_address; | ||
269 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = | ||
270 | table->length; | ||
271 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = flags; | ||
272 | |||
273 | acpi_tb_print_table_header(dsdt_address, table); | ||
274 | |||
275 | /* Global integer width is based upon revision of the DSDT */ | ||
276 | |||
277 | acpi_ut_set_integer_width(table->revision); | ||
278 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
279 | |||
280 | no_dsdt: | ||
281 | if (!facs_address) { | ||
282 | return; | ||
283 | } | ||
262 | 284 | ||
263 | table->checksum = acpi_tb_generate_checksum(table); | 285 | table = |
286 | acpi_os_map_memory(facs_address, sizeof(struct acpi_table_header)); | ||
287 | if (!table) { | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | /* Initialize the FACS table */ | ||
292 | |||
293 | ACPI_MOVE_32_TO_32(& | ||
294 | (acpi_gbl_root_table_list. | ||
295 | tables[ACPI_TABLE_INDEX_FACS].signature), | ||
296 | ACPI_SIG_FACS); | ||
297 | |||
298 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].address = | ||
299 | facs_address; | ||
300 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].length = | ||
301 | table->length; | ||
302 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].flags = flags; | ||
303 | |||
304 | ACPI_INFO((AE_INFO, "%4.4s @ 0x%p", | ||
305 | table->signature, ACPI_CAST_PTR(void, facs_address))); | ||
306 | |||
307 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
264 | } | 308 | } |
265 | 309 | ||
266 | /******************************************************************************* | 310 | /******************************************************************************* |
267 | * | 311 | * |
268 | * FUNCTION: acpi_tb_verify_table_checksum | 312 | * FUNCTION: acpi_tb_parse_root_table |
269 | * | 313 | * |
270 | * PARAMETERS: *table_header - ACPI table to verify | 314 | * PARAMETERS: Rsdp - Pointer to the RSDP |
315 | * Flags - Flags | ||
316 | * | ||
317 | * RETURN: Status | ||
271 | * | 318 | * |
272 | * RETURN: 8 bit checksum of table | 319 | * DESCRIPTION: This function is called to parse the Root System Description |
320 | * Table (RSDT or XSDT) | ||
273 | * | 321 | * |
274 | * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares | 322 | * NOTE: Tables are mapped (not copied) for efficiency. The FACS must |
275 | * it to the existing checksum value. | 323 | * be mapped and cannot be copied because it contains the actual |
324 | * memory location of the ACPI Global Lock. | ||
276 | * | 325 | * |
277 | ******************************************************************************/ | 326 | ******************************************************************************/ |
278 | 327 | ||
279 | acpi_status | 328 | acpi_status acpi_tb_parse_root_table(struct acpi_table_rsdp *rsdp, u8 flags) |
280 | acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) | ||
281 | { | 329 | { |
330 | struct acpi_table_header *table; | ||
331 | acpi_physical_address address; | ||
332 | u32 length; | ||
333 | u8 *table_entry; | ||
334 | acpi_native_uint i; | ||
335 | acpi_native_uint pointer_size; | ||
336 | u32 table_count; | ||
282 | u8 checksum; | 337 | u8 checksum; |
338 | acpi_status status; | ||
339 | |||
340 | ACPI_FUNCTION_TRACE(tb_parse_root_table); | ||
341 | |||
342 | /* Differentiate between RSDT and XSDT root tables */ | ||
343 | |||
344 | if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { | ||
345 | /* | ||
346 | * Root table is an XSDT (64-bit physical addresses). We must use the | ||
347 | * XSDT if the revision is > 1 and the XSDT pointer is present, as per | ||
348 | * the ACPI specification. | ||
349 | */ | ||
350 | address = (acpi_native_uint) rsdp->xsdt_physical_address; | ||
351 | pointer_size = sizeof(u64); | ||
352 | } else { | ||
353 | /* Root table is an RSDT (32-bit physical addresses) */ | ||
354 | |||
355 | address = (acpi_native_uint) rsdp->rsdt_physical_address; | ||
356 | pointer_size = sizeof(u32); | ||
357 | } | ||
283 | 358 | ||
284 | ACPI_FUNCTION_TRACE(tb_verify_table_checksum); | 359 | /* Map the table header to get the full table length */ |
285 | 360 | ||
286 | /* Compute the checksum on the table */ | 361 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); |
362 | if (!table) { | ||
363 | return (AE_NO_MEMORY); | ||
364 | } | ||
365 | |||
366 | /* Get the length of the full table, verify length and map entire table */ | ||
367 | |||
368 | length = table->length; | ||
369 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
370 | |||
371 | if (length < sizeof(struct acpi_table_header)) { | ||
372 | ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", | ||
373 | length)); | ||
374 | return (AE_INVALID_TABLE_LENGTH); | ||
375 | } | ||
376 | |||
377 | table = acpi_os_map_memory(address, length); | ||
378 | if (!table) { | ||
379 | return (AE_NO_MEMORY); | ||
380 | } | ||
381 | |||
382 | /* Validate the root table checksum */ | ||
383 | |||
384 | checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); | ||
385 | #if (ACPI_CHECKSUM_ABORT) | ||
386 | |||
387 | if (checksum) { | ||
388 | acpi_os_unmap_memory(table, length); | ||
389 | return (AE_BAD_CHECKSUM); | ||
390 | } | ||
391 | #endif | ||
392 | |||
393 | acpi_tb_print_table_header(address, table); | ||
394 | |||
395 | /* Calculate the number of tables described in the root table */ | ||
396 | |||
397 | table_count = | ||
398 | (table->length - sizeof(struct acpi_table_header)) / pointer_size; | ||
399 | |||
400 | /* Setup loop */ | ||
287 | 401 | ||
288 | checksum = acpi_tb_generate_checksum(table_header); | 402 | table_entry = |
403 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); | ||
404 | acpi_gbl_root_table_list.count = 2; | ||
289 | 405 | ||
290 | /* Checksum ok? */ | 406 | /* |
407 | * Initialize the ACPI table entries | ||
408 | * First two entries in the table array are reserved for the DSDT and FACS | ||
409 | */ | ||
410 | for (i = 0; i < table_count; ++i, table_entry += pointer_size) { | ||
291 | 411 | ||
292 | if (checksum == table_header->checksum) { | 412 | /* Ensure there is room for another table entry */ |
293 | return_ACPI_STATUS(AE_OK); | 413 | |
414 | if (acpi_gbl_root_table_list.count >= | ||
415 | acpi_gbl_root_table_list.size) { | ||
416 | status = acpi_tb_resize_root_table_list(); | ||
417 | if (ACPI_FAILURE(status)) { | ||
418 | ACPI_WARNING((AE_INFO, | ||
419 | "Truncating %u table entries!", | ||
420 | (unsigned) | ||
421 | (acpi_gbl_root_table_list.size - | ||
422 | acpi_gbl_root_table_list. | ||
423 | count))); | ||
424 | break; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | /* Get the physical address (32-bit for RSDT, 64-bit for XSDT) */ | ||
429 | |||
430 | if (pointer_size == sizeof(u32)) { | ||
431 | acpi_gbl_root_table_list. | ||
432 | tables[acpi_gbl_root_table_list.count].address = | ||
433 | (acpi_physical_address) (*ACPI_CAST_PTR | ||
434 | (u32, table_entry)); | ||
435 | } else { | ||
436 | acpi_gbl_root_table_list. | ||
437 | tables[acpi_gbl_root_table_list.count].address = | ||
438 | (acpi_physical_address) (*ACPI_CAST_PTR | ||
439 | (u64, table_entry)); | ||
440 | } | ||
441 | |||
442 | acpi_gbl_root_table_list.count++; | ||
294 | } | 443 | } |
295 | 444 | ||
296 | ACPI_WARNING((AE_INFO, | 445 | /* |
297 | "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", | 446 | * It is not possible to map more than one entry in some environments, |
298 | table_header->signature, table_header->checksum, | 447 | * so unmap the root table here before mapping other tables |
299 | checksum)); | 448 | */ |
449 | acpi_os_unmap_memory(table, length); | ||
450 | |||
451 | /* Initialize all tables other than the DSDT and FACS */ | ||
452 | |||
453 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { | ||
454 | address = acpi_gbl_root_table_list.tables[i].address; | ||
455 | length = sizeof(struct acpi_table_header); | ||
456 | |||
457 | table = acpi_os_map_memory(address, length); | ||
458 | if (!table) { | ||
459 | continue; | ||
460 | } | ||
461 | |||
462 | acpi_gbl_root_table_list.tables[i].length = table->length; | ||
463 | acpi_gbl_root_table_list.tables[i].flags = flags; | ||
464 | |||
465 | ACPI_MOVE_32_TO_32(& | ||
466 | (acpi_gbl_root_table_list.tables[i]. | ||
467 | signature), table->signature); | ||
468 | |||
469 | acpi_tb_print_table_header(address, table); | ||
470 | |||
471 | /* | ||
472 | * Special case for the FADT because of multiple versions - | ||
473 | * get a local copy and convert to common format | ||
474 | */ | ||
475 | if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FADT)) { | ||
476 | acpi_os_unmap_memory(table, length); | ||
477 | length = table->length; | ||
478 | |||
479 | table = acpi_os_map_memory(address, length); | ||
480 | if (!table) { | ||
481 | continue; | ||
482 | } | ||
483 | |||
484 | /* Copy the entire FADT locally */ | ||
485 | |||
486 | ACPI_MEMCPY(&acpi_gbl_FADT, table, | ||
487 | ACPI_MIN(table->length, | ||
488 | sizeof(struct acpi_table_fadt))); | ||
489 | |||
490 | /* Small table means old revision, convert to new */ | ||
491 | |||
492 | if (table->length < sizeof(struct acpi_table_fadt)) { | ||
493 | acpi_tb_convert_fadt(ACPI_CAST_PTR | ||
494 | (struct acpi_table_fadt, | ||
495 | table)); | ||
496 | } | ||
497 | |||
498 | /* Unmap original FADT */ | ||
300 | 499 | ||
301 | return_ACPI_STATUS(AE_BAD_CHECKSUM); | 500 | acpi_os_unmap_memory(table, length); |
501 | acpi_tb_parse_fadt(&acpi_gbl_FADT, flags); | ||
502 | } else { | ||
503 | acpi_os_unmap_memory(table, length); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | return_ACPI_STATUS(AE_OK); | ||
302 | } | 508 | } |
303 | 509 | ||
304 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 510 | /****************************************************************************** |
305 | /******************************************************************************* | ||
306 | * | 511 | * |
307 | * FUNCTION: acpi_tb_handle_to_object | 512 | * FUNCTION: acpi_tb_map |
308 | * | 513 | * |
309 | * PARAMETERS: table_id - Id for which the function is searching | 514 | * PARAMETERS: Address - Address to be mapped |
310 | * table_desc - Pointer to return the matching table | 515 | * Length - Length to be mapped |
311 | * descriptor. | 516 | * Flags - Logical or physical addressing mode |
312 | * | 517 | * |
313 | * RETURN: Search the tables to find one with a matching table_id and | 518 | * RETURN: Pointer to mapped region |
314 | * return a pointer to that table descriptor. | ||
315 | * | 519 | * |
316 | ******************************************************************************/ | 520 | * DESCRIPTION: Maps memory according to flag |
521 | * | ||
522 | *****************************************************************************/ | ||
317 | 523 | ||
318 | acpi_status | 524 | void *acpi_tb_map(acpi_physical_address address, u32 length, u32 flags) |
319 | acpi_tb_handle_to_object(u16 table_id, | ||
320 | struct acpi_table_desc **return_table_desc) | ||
321 | { | 525 | { |
322 | u32 i; | ||
323 | struct acpi_table_desc *table_desc; | ||
324 | 526 | ||
325 | ACPI_FUNCTION_NAME(tb_handle_to_object); | 527 | if (flags == ACPI_TABLE_ORIGIN_MAPPED) { |
528 | return (acpi_os_map_memory(address, length)); | ||
529 | } else { | ||
530 | return (ACPI_CAST_PTR(void, address)); | ||
531 | } | ||
532 | } | ||
326 | 533 | ||
327 | for (i = 0; i < ACPI_TABLE_MAX; i++) { | 534 | /****************************************************************************** |
328 | table_desc = acpi_gbl_table_lists[i].next; | 535 | * |
329 | while (table_desc) { | 536 | * FUNCTION: acpi_tb_unmap |
330 | if (table_desc->table_id == table_id) { | 537 | * |
331 | *return_table_desc = table_desc; | 538 | * PARAMETERS: Pointer - To mapped region |
332 | return (AE_OK); | 539 | * Length - Length to be unmapped |
333 | } | 540 | * Flags - Logical or physical addressing mode |
541 | * | ||
542 | * RETURN: None | ||
543 | * | ||
544 | * DESCRIPTION: Unmaps memory according to flag | ||
545 | * | ||
546 | *****************************************************************************/ | ||
334 | 547 | ||
335 | table_desc = table_desc->next; | 548 | void acpi_tb_unmap(void *pointer, u32 length, u32 flags) |
336 | } | 549 | { |
337 | } | ||
338 | 550 | ||
339 | ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); | 551 | if (flags == ACPI_TABLE_ORIGIN_MAPPED) { |
340 | return (AE_BAD_PARAMETER); | 552 | acpi_os_unmap_memory(pointer, length); |
553 | } | ||
341 | } | 554 | } |
342 | #endif | ||