summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/tables.c
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2019-03-11 16:55:57 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-04 12:41:12 -0400
commit60574d1e05b094d222162260dd9cac49f4d0996a (patch)
treeed8ec87acba8ab7d4ce141605b16c3aab12fd6fc /drivers/acpi/tables.c
parentc03a0fd0b609e2f5c669c2b7f27c8e1928e9196e (diff)
acpi: Create subtable parsing infrastructure
Parsing entries in an ACPI table had assumed a generic header structure. There is no standard ACPI header, though, so less common layouts with different field sizes required custom parsers to go through their subtable entry list. Create the infrastructure for adding different table types so parsing the entries array may be more reused for all ACPI system tables and the common code doesn't need to be duplicated. Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Keith Busch <keith.busch@intel.com> Tested-by: Brice Goglin <Brice.Goglin@inria.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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) {