@@ -46,11 +46,79 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
46
46
/** MACA signature */
47
47
#define MACA_SIGNATURE ACPI_SIGNATURE ( 'M', 'A', 'C', 'A' )
48
48
49
- /** Maximum number of bytes to skip after AMAC/MACA signature
49
+ /** RTMA signature */
50
+ #define RTMA_SIGNATURE ACPI_SIGNATURE ( 'R', 'T', 'M', 'A' )
51
+
52
+ /** Maximum number of bytes to skip after ACPI signature
50
53
*
51
54
* This is entirely empirical.
52
55
*/
53
- #define AUXMAC_MAX_SKIP 8
56
+ #define ACPIMAC_MAX_SKIP 8
57
+
58
+ /** An ACPI MAC extraction mechanism */
59
+ struct acpimac_extractor {
60
+ /** Prefix string */
61
+ const char * prefix ;
62
+ /** Encoded MAC length */
63
+ size_t len ;
64
+ /** Decode MAC
65
+ *
66
+ * @v mac Encoded MAC
67
+ * @v hw_addr MAC address to fill in
68
+ * @ret rc Return status code
69
+ */
70
+ int ( * decode ) ( const char * mac , uint8_t * hw_addr );
71
+ };
72
+
73
+ /**
74
+ * Decode Base16-encoded MAC address
75
+ *
76
+ * @v mac Encoded MAC
77
+ * @v hw_addr MAC address to fill in
78
+ * @ret rc Return status code
79
+ */
80
+ static int acpimac_decode_base16 ( const char * mac , uint8_t * hw_addr ) {
81
+ int len ;
82
+ int rc ;
83
+
84
+ /* Attempt to base16-decode MAC address */
85
+ len = base16_decode ( mac , hw_addr , ETH_ALEN );
86
+ if ( len < 0 ) {
87
+ rc = len ;
88
+ DBGC ( colour , "ACPI could not decode base16 MAC \"%s\": %s\n" ,
89
+ mac , strerror ( rc ) );
90
+ return rc ;
91
+ }
92
+
93
+ return 0 ;
94
+ }
95
+
96
+ /**
97
+ * Decode raw MAC address
98
+ *
99
+ * @v mac Encoded MAC
100
+ * @v hw_addr MAC address to fill in
101
+ * @ret rc Return status code
102
+ */
103
+ static int acpimac_decode_raw ( const char * mac , uint8_t * hw_addr ) {
104
+
105
+ memcpy ( hw_addr , mac , ETH_ALEN );
106
+ return 0 ;
107
+ }
108
+
109
+ /** "_AUXMAC_" extraction mechanism */
110
+ static struct acpimac_extractor acpimac_auxmac = {
111
+ .prefix = "_AUXMAC_#" ,
112
+ .len = ( ETH_ALEN * 2 ),
113
+ .decode = acpimac_decode_base16 ,
114
+ };
115
+
116
+ /** "_RTXMAC_" extraction mechanism */
117
+ static struct acpimac_extractor acpimac_rtxmac = {
118
+ .prefix = "_RTXMAC_#" ,
119
+ .len = ETH_ALEN ,
120
+ .decode = acpimac_decode_raw ,
121
+ };
54
122
55
123
/**
56
124
* Extract MAC address from DSDT/SSDT
@@ -59,6 +127,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
59
127
* @v len Length of DSDT/SSDT
60
128
* @v offset Offset of signature within DSDT/SSDT
61
129
* @v data Data buffer
130
+ * @v extractor ACPI MAC address extractor
62
131
* @ret rc Return status code
63
132
*
64
133
* Some vendors provide a "system MAC address" within the DSDT/SSDT,
@@ -72,51 +141,44 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
72
141
* string that appears shortly after an "AMAC" or "MACA" signature.
73
142
* This should work for most implementations encountered in practice.
74
143
*/
75
- static int acpi_extract_mac ( userptr_t zsdt , size_t len , size_t offset ,
76
- void * data ) {
77
- static const char prefix [ 9 ] = "_AUXMAC_#" ;
144
+ static int acpimac_extract ( userptr_t zsdt , size_t len , size_t offset ,
145
+ void * data , struct acpimac_extractor * extractor ) {
146
+ size_t prefix_len = strlen ( extractor -> prefix ) ;
78
147
uint8_t * hw_addr = data ;
79
148
size_t skip = 0 ;
80
- char auxmac [ sizeof ( prefix ) /* "_AUXMAC_#" */ +
81
- ( ETH_ALEN * 2 ) /* MAC */ + 1 /* "#" */ + 1 /* NUL */ ];
82
- char * mac = & auxmac [ sizeof ( prefix ) ];
83
- int decoded_len ;
149
+ char buf [ prefix_len + extractor -> len + 1 /* "#" */ + 1 /* NUL */ ];
150
+ char * mac = & buf [prefix_len ];
84
151
int rc ;
85
152
86
153
/* Skip signature and at least one tag byte */
87
154
offset += ( 4 /* signature */ + 1 /* tag byte */ );
88
155
89
- /* Scan for "_AUXMAC_#.....#" close to signature */
156
+ /* Scan for suitable string close to signature */
90
157
for ( skip = 0 ;
91
- ( ( skip < AUXMAC_MAX_SKIP ) &&
92
- ( offset + skip + sizeof ( auxmac ) ) < len ) ;
158
+ ( ( skip < ACPIMAC_MAX_SKIP ) &&
159
+ ( offset + skip + sizeof ( buf ) ) <= len ) ;
93
160
skip ++ ) {
94
161
95
162
/* Read value */
96
- copy_from_user ( auxmac , zsdt , ( offset + skip ),
97
- sizeof ( auxmac ) );
163
+ copy_from_user ( buf , zsdt , ( offset + skip ),
164
+ sizeof ( buf ) );
98
165
99
166
/* Check for expected format */
100
- if ( memcmp ( auxmac , prefix , sizeof ( prefix ) ) != 0 )
167
+ if ( memcmp ( buf , extractor -> prefix , prefix_len ) != 0 )
101
168
continue ;
102
- if ( auxmac [ sizeof ( auxmac ) - 2 ] != '#' )
169
+ if ( buf [ sizeof ( buf ) - 2 ] != '#' )
103
170
continue ;
104
- if ( auxmac [ sizeof ( auxmac ) - 1 ] != '\0' )
171
+ if ( buf [ sizeof ( buf ) - 1 ] != '\0' )
105
172
continue ;
106
- DBGC ( colour , "ACPI found MAC string \"%s\"\n" , auxmac );
173
+ DBGC ( colour , "ACPI found MAC:\n" );
174
+ DBGC_HDA ( colour , ( offset + skip ), buf , sizeof ( buf ) );
107
175
108
176
/* Terminate MAC address string */
109
- mac = & auxmac [ sizeof ( prefix ) ];
110
- mac [ ETH_ALEN * 2 ] = '\0' ;
177
+ mac [extractor -> len ] = '\0' ;
111
178
112
179
/* Decode MAC address */
113
- decoded_len = base16_decode ( mac , hw_addr , ETH_ALEN );
114
- if ( decoded_len < 0 ) {
115
- rc = decoded_len ;
116
- DBGC ( colour , "ACPI could not decode MAC \"%s\": %s\n" ,
117
- mac , strerror ( rc ) );
180
+ if ( ( rc = extractor -> decode ( mac , hw_addr ) ) != 0 )
118
181
return rc ;
119
- }
120
182
121
183
/* Check MAC address validity */
122
184
if ( ! is_valid_ether_addr ( hw_addr ) ) {
@@ -131,6 +193,36 @@ static int acpi_extract_mac ( userptr_t zsdt, size_t len, size_t offset,
131
193
return - ENOENT ;
132
194
}
133
195
196
+ /**
197
+ * Extract "_AUXMAC_" MAC address from DSDT/SSDT
198
+ *
199
+ * @v zsdt DSDT or SSDT
200
+ * @v len Length of DSDT/SSDT
201
+ * @v offset Offset of signature within DSDT/SSDT
202
+ * @v data Data buffer
203
+ * @ret rc Return status code
204
+ */
205
+ static int acpimac_extract_auxmac ( userptr_t zsdt , size_t len , size_t offset ,
206
+ void * data ) {
207
+
208
+ return acpimac_extract ( zsdt , len , offset , data , & acpimac_auxmac );
209
+ }
210
+
211
+ /**
212
+ * Extract "_RTXMAC_" MAC address from DSDT/SSDT
213
+ *
214
+ * @v zsdt DSDT or SSDT
215
+ * @v len Length of DSDT/SSDT
216
+ * @v offset Offset of signature within DSDT/SSDT
217
+ * @v data Data buffer
218
+ * @ret rc Return status code
219
+ */
220
+ static int acpimac_extract_rtxmac ( userptr_t zsdt , size_t len , size_t offset ,
221
+ void * data ) {
222
+
223
+ return acpimac_extract ( zsdt , len , offset , data , & acpimac_rtxmac );
224
+ }
225
+
134
226
/**
135
227
* Extract MAC address from DSDT/SSDT
136
228
*
@@ -142,12 +234,17 @@ int acpi_mac ( uint8_t *hw_addr ) {
142
234
143
235
/* Look for an "AMAC" address */
144
236
if ( ( rc = acpi_extract ( AMAC_SIGNATURE , hw_addr ,
145
- acpi_extract_mac ) ) == 0 )
237
+ acpimac_extract_auxmac ) ) == 0 )
146
238
return 0 ;
147
239
148
240
/* Look for a "MACA" address */
149
241
if ( ( rc = acpi_extract ( MACA_SIGNATURE , hw_addr ,
150
- acpi_extract_mac ) ) == 0 )
242
+ acpimac_extract_auxmac ) ) == 0 )
243
+ return 0 ;
244
+
245
+ /* Look for a "RTMA" address */
246
+ if ( ( rc = acpi_extract ( RTMA_SIGNATURE , hw_addr ,
247
+ acpimac_extract_rtxmac ) ) == 0 )
151
248
return 0 ;
152
249
153
250
return - ENOENT ;
0 commit comments