summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/tables.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/tables.c')
-rw-r--r--drivers/acpi/tables.c67
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 8fccbe49612a..7553774a22b7 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -49,6 +49,15 @@ static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
49 49
50static int acpi_apic_instance __initdata; 50static int acpi_apic_instance __initdata;
51 51
52enum acpi_subtable_type {
53 ACPI_SUBTABLE_COMMON,
54};
55
56struct acpi_subtable_entry {
57 union acpi_subtable_headers *hdr;
58 enum acpi_subtable_type type;
59};
60
52/* 61/*
53 * Disable table checksum verification for the early stage due to the size 62 * Disable table checksum verification for the early stage due to the size
54 * limitation of the current x86 early mapping implementation. 63 * limitation of the current x86 early mapping implementation.
@@ -217,6 +226,42 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
217 } 226 }
218} 227}
219 228
229static unsigned long __init
230acpi_get_entry_type(struct acpi_subtable_entry *entry)
231{
232 switch (entry->type) {
233 case ACPI_SUBTABLE_COMMON:
234 return entry->hdr->common.type;
235 }
236 return 0;
237}
238
239static unsigned long __init
240acpi_get_entry_length(struct acpi_subtable_entry *entry)
241{
242 switch (entry->type) {
243 case ACPI_SUBTABLE_COMMON:
244 return entry->hdr->common.length;
245 }
246 return 0;
247}
248
249static unsigned long __init
250acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
251{
252 switch (entry->type) {
253 case ACPI_SUBTABLE_COMMON:
254 return sizeof(entry->hdr->common);
255 }
256 return 0;
257}
258
259static enum acpi_subtable_type __init
260acpi_get_subtable_type(char *id)
261{
262 return ACPI_SUBTABLE_COMMON;
263}
264
220/** 265/**
221 * acpi_parse_entries_array - for each proc_num find a suitable subtable 266 * acpi_parse_entries_array - for each proc_num find a suitable subtable
222 * 267 *
@@ -246,8 +291,8 @@ acpi_parse_entries_array(char *id, unsigned long table_size,
246 struct acpi_subtable_proc *proc, int proc_num, 291 struct acpi_subtable_proc *proc, int proc_num,
247 unsigned int max_entries) 292 unsigned int max_entries)
248{ 293{
249 struct acpi_subtable_header *entry; 294 struct acpi_subtable_entry entry;
250 unsigned long table_end; 295 unsigned long table_end, subtable_len, entry_len;
251 int count = 0; 296 int count = 0;
252 int errs = 0; 297 int errs = 0;
253 int i; 298 int i;
@@ -270,19 +315,20 @@ acpi_parse_entries_array(char *id, unsigned long table_size,
270 315
271 /* Parse all entries looking for a match. */ 316 /* Parse all entries looking for a match. */
272 317
273 entry = (struct acpi_subtable_header *) 318 entry.type = acpi_get_subtable_type(id);
319 entry.hdr = (union acpi_subtable_headers *)
274 ((unsigned long)table_header + table_size); 320 ((unsigned long)table_header + table_size);
321 subtable_len = acpi_get_subtable_header_length(&entry);
275 322
276 while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < 323 while (((unsigned long)entry.hdr) + subtable_len < table_end) {
277 table_end) {
278 if (max_entries && count >= max_entries) 324 if (max_entries && count >= max_entries)
279 break; 325 break;
280 326
281 for (i = 0; i < proc_num; i++) { 327 for (i = 0; i < proc_num; i++) {
282 if (entry->type != proc[i].id) 328 if (acpi_get_entry_type(&entry) != proc[i].id)
283 continue; 329 continue;
284 if (!proc[i].handler || 330 if (!proc[i].handler ||
285 (!errs && proc[i].handler(entry, table_end))) { 331 (!errs && proc[i].handler(entry.hdr, table_end))) {
286 errs++; 332 errs++;
287 continue; 333 continue;
288 } 334 }
@@ -297,13 +343,14 @@ acpi_parse_entries_array(char *id, unsigned long table_size,
297 * If entry->length is 0, break from this loop to avoid 343 * If entry->length is 0, break from this loop to avoid
298 * infinite loop. 344 * infinite loop.
299 */ 345 */
300 if (entry->length == 0) { 346 entry_len = acpi_get_entry_length(&entry);
347 if (entry_len == 0) {
301 pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id); 348 pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
302 return -EINVAL; 349 return -EINVAL;
303 } 350 }
304 351
305 entry = (struct acpi_subtable_header *) 352 entry.hdr = (union acpi_subtable_headers *)
306 ((unsigned long)entry + entry->length); 353 ((unsigned long)entry.hdr + entry_len);
307 } 354 }
308 355
309 if (max_entries && count > max_entries) { 356 if (max_entries && count > max_entries) {