Browse Source

[acpi] Expose ACPI tables via settings mechanism

Allow values to be read from ACPI tables using the syntax

  ${acpi/<signature>.<index>.0.<offset>.<length>}

where <signature> is the ACPI table signature as a 32-bit hexadecimal
number (e.g. 0x41504093 for the 'APIC' signature on the MADT), <index>
is the index into the array of tables matching this signature,
<offset> is the byte offset within the table, and <length> is the
field length in bytes.

Numeric values are returned in reverse byte order, since ACPI numeric
values are usually little-endian.

For example:

  ${acpi/0x41504943.0.0.0.0}           - entire MADT table in raw hex
  ${acpi/0x41504943.0.0.0x0a.6:string} - MADT table OEM ID
  ${acpi/0x41504943.0.0.0x24.4:uint32} - local APIC address

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
356f6c1b64
4 changed files with 166 additions and 0 deletions
  1. 3
    0
      src/config/config.c
  2. 1
    0
      src/config/settings.h
  3. 161
    0
      src/core/acpi_settings.c
  4. 1
    0
      src/include/ipxe/errfile.h

+ 3
- 0
src/config/config.c View File

@@ -337,6 +337,9 @@ REQUIRE_OBJECT ( memmap_settings );
337 337
 #ifdef VRAM_SETTINGS
338 338
 REQUIRE_OBJECT ( vram_settings );
339 339
 #endif
340
+#ifdef ACPI_SETTINGS
341
+REQUIRE_OBJECT ( acpi_settings );
342
+#endif
340 343
 
341 344
 /*
342 345
  * Drag in selected keyboard map

+ 1
- 0
src/config/settings.h View File

@@ -14,6 +14,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
14 14
 //#define	MEMMAP_SETTINGS	/* Memory map settings */
15 15
 //#define	VMWARE_SETTINGS	/* VMware GuestInfo settings */
16 16
 //#define	VRAM_SETTINGS	/* Video RAM dump settings */
17
+//#define	ACPI_SETTINGS	/* ACPI settings */
17 18
 
18 19
 #include <config/named.h>
19 20
 #include NAMED_CONFIG(settings.h)

+ 161
- 0
src/core/acpi_settings.c View File

@@ -0,0 +1,161 @@
1
+/*
2
+ * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/**
27
+ * @file
28
+ *
29
+ * ACPI settings
30
+ *
31
+ */
32
+
33
+#include <string.h>
34
+#include <errno.h>
35
+#include <ipxe/init.h>
36
+#include <ipxe/settings.h>
37
+#include <ipxe/acpi.h>
38
+
39
+/** ACPI settings scope */
40
+static const struct settings_scope acpi_settings_scope;
41
+
42
+/**
43
+ * Check applicability of ACPI setting
44
+ *
45
+ * @v settings		Settings block
46
+ * @v setting		Setting
47
+ * @ret applies		Setting applies within this settings block
48
+ */
49
+static int acpi_settings_applies ( struct settings *settings __unused,
50
+				   const struct setting *setting ) {
51
+
52
+	return ( setting->scope == &acpi_settings_scope );
53
+}
54
+
55
+/**
56
+ * Fetch value of ACPI setting
57
+ *
58
+ * @v settings		Settings block
59
+ * @v setting		Setting to fetch
60
+ * @v data		Buffer to fill with setting data
61
+ * @v len		Length of buffer
62
+ * @ret len		Length of setting data, or negative error
63
+ */
64
+static int acpi_settings_fetch ( struct settings *settings,
65
+				 struct setting *setting,
66
+				 void *data, size_t len ) {
67
+	struct acpi_header acpi;
68
+	uint32_t tag_high;
69
+	uint32_t tag_low;
70
+	uint32_t tag_signature;
71
+	unsigned int tag_index;
72
+	size_t tag_offset;
73
+	size_t tag_len;
74
+	userptr_t table;
75
+	size_t offset;
76
+	size_t max_len;
77
+	int delta;
78
+	unsigned int i;
79
+
80
+	/* Parse settings tag */
81
+	tag_high = ( setting->tag >> 32 );
82
+	tag_low = setting->tag;
83
+	tag_signature = bswap_32 ( tag_high );
84
+	tag_index = ( ( tag_low >> 24 ) & 0xff );
85
+	tag_offset = ( ( tag_low >> 8 ) & 0xffff );
86
+	tag_len = ( ( tag_low >> 0 ) & 0xff );
87
+	DBGC ( settings, "ACPI %s.%d offset %#zx length %#zx\n",
88
+	       acpi_name ( tag_signature ), tag_index, tag_offset, tag_len );
89
+
90
+	/* Locate ACPI table */
91
+	table = acpi_find ( tag_signature, tag_index );
92
+	if ( ! table )
93
+		return -ENOENT;
94
+
95
+	/* Read table header */
96
+	copy_from_user ( &acpi, table, 0, sizeof ( acpi ) );
97
+
98
+	/* Calculate starting offset and maximum available length */
99
+	max_len = le32_to_cpu ( acpi.length );
100
+	if ( tag_offset > max_len )
101
+		return -ENOENT;
102
+	offset = tag_offset;
103
+	max_len -= offset;
104
+
105
+	/* Restrict to requested length, if specified */
106
+	if ( tag_len && ( tag_len < max_len ) )
107
+		max_len = tag_len;
108
+
109
+	/* Invert endianness for numeric settings */
110
+	if ( setting->type && setting->type->numerate ) {
111
+		offset += ( max_len - 1 );
112
+		delta = -1;
113
+	} else {
114
+		delta = +1;
115
+	}
116
+
117
+	/* Read data */
118
+	for ( i = 0 ; ( ( i < max_len ) && ( i < len ) ) ; i++ ) {
119
+		copy_from_user ( data, table, offset, 1 );
120
+		data++;
121
+		offset += delta;
122
+	}
123
+
124
+	/* Set type if not already specified */
125
+	if ( ! setting->type )
126
+		setting->type = &setting_type_hexraw;
127
+
128
+	return max_len;
129
+}
130
+
131
+/** ACPI settings operations */
132
+static struct settings_operations acpi_settings_operations = {
133
+	.applies = acpi_settings_applies,
134
+	.fetch = acpi_settings_fetch,
135
+};
136
+
137
+/** ACPI settings */
138
+static struct settings acpi_settings = {
139
+	.refcnt = NULL,
140
+	.siblings = LIST_HEAD_INIT ( acpi_settings.siblings ),
141
+	.children = LIST_HEAD_INIT ( acpi_settings.children ),
142
+	.op = &acpi_settings_operations,
143
+	.default_scope = &acpi_settings_scope,
144
+};
145
+
146
+/** Initialise ACPI settings */
147
+static void acpi_settings_init ( void ) {
148
+	int rc;
149
+
150
+	if ( ( rc = register_settings ( &acpi_settings, NULL,
151
+					"acpi" ) ) != 0 ) {
152
+		DBG ( "ACPI could not register settings: %s\n",
153
+		      strerror ( rc ) );
154
+		return;
155
+	}
156
+}
157
+
158
+/** ACPI settings initialiser */
159
+struct init_fn acpi_settings_init_fn __init_fn ( INIT_NORMAL ) = {
160
+	.initialise = acpi_settings_init,
161
+};

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -366,6 +366,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
366 366
 #define ERRFILE_efi_local	      ( ERRFILE_OTHER | 0x004d0000 )
367 367
 #define ERRFILE_efi_entropy	      ( ERRFILE_OTHER | 0x004e0000 )
368 368
 #define ERRFILE_cert_cmd	      ( ERRFILE_OTHER | 0x004f0000 )
369
+#define ERRFILE_acpi_settings	      ( ERRFILE_OTHER | 0x00500000 )
369 370
 
370 371
 /** @} */
371 372
 

Loading…
Cancel
Save