iPXE
acpimac.c File Reference

ACPI MAC address. More...

#include <string.h>
#include <errno.h>
#include <ipxe/acpi.h>
#include <ipxe/base16.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/settings.h>
#include <ipxe/acpimac.h>

Go to the source code of this file.

Data Structures

struct  acpimac_extractor
 An ACPI MAC extraction mechanism. More...

Macros

#define colour   FADT_SIGNATURE
 Colour for debug messages.
#define AMAC_SIGNATURE   ACPI_SIGNATURE ( 'A', 'M', 'A', 'C' )
 AMAC signature.
#define MACA_SIGNATURE   ACPI_SIGNATURE ( 'M', 'A', 'C', 'A' )
 MACA signature.
#define RTMA_SIGNATURE   ACPI_SIGNATURE ( 'R', 'T', 'M', 'A' )
 RTMA signature.
#define ACPIMAC_MAX_SKIP   8
 Maximum number of bytes to skip after ACPI signature.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int acpimac_decode_base16 (const char *mac, uint8_t *hw_addr)
 Decode Base16-encoded MAC address.
static int acpimac_decode_raw (const char *mac, uint8_t *hw_addr)
 Decode raw MAC address.
static int acpimac_extract (const struct acpi_header *zsdt, size_t len, size_t offset, void *data, struct acpimac_extractor *extractor)
 Extract MAC address from DSDT/SSDT.
static int acpimac_extract_auxmac (const struct acpi_header *zsdt, size_t len, size_t offset, void *data)
 Extract "_AUXMAC_" MAC address from DSDT/SSDT.
static int acpimac_extract_rtxmac (const struct acpi_header *zsdt, size_t len, size_t offset, void *data)
 Extract "_RTXMAC_" MAC address from DSDT/SSDT.
int acpi_mac (uint8_t *hw_addr)
 Extract MAC address from DSDT/SSDT.
static int sysmac_fetch (void *data, size_t len)
 Fetch system MAC address setting.
const struct setting sysmac_setting __setting (SETTING_MISC, sysmac)
 System MAC address setting.

Variables

static struct acpimac_extractor acpimac_auxmac
 "_AUXMAC_" extraction mechanism
static struct acpimac_extractor acpimac_rtxmac
 "_RTXMAC_" extraction mechanism
struct builtin_setting sysmac_builtin_setting __builtin_setting
 System MAC address built-in setting.

Detailed Description

ACPI MAC address.

Definition in file acpimac.c.

Macro Definition Documentation

◆ colour

#define colour   FADT_SIGNATURE

Colour for debug messages.

Definition at line 43 of file acpimac.c.

◆ AMAC_SIGNATURE

#define AMAC_SIGNATURE   ACPI_SIGNATURE ( 'A', 'M', 'A', 'C' )

AMAC signature.

Definition at line 46 of file acpimac.c.

Referenced by acpi_mac().

◆ MACA_SIGNATURE

#define MACA_SIGNATURE   ACPI_SIGNATURE ( 'M', 'A', 'C', 'A' )

MACA signature.

Definition at line 49 of file acpimac.c.

Referenced by acpi_mac().

◆ RTMA_SIGNATURE

#define RTMA_SIGNATURE   ACPI_SIGNATURE ( 'R', 'T', 'M', 'A' )

RTMA signature.

Definition at line 52 of file acpimac.c.

Referenced by acpi_mac().

◆ ACPIMAC_MAX_SKIP

#define ACPIMAC_MAX_SKIP   8

Maximum number of bytes to skip after ACPI signature.

This is entirely empirical.

Definition at line 58 of file acpimac.c.

Referenced by acpimac_extract().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ acpimac_decode_base16()

int acpimac_decode_base16 ( const char * mac,
uint8_t * hw_addr )
static

Decode Base16-encoded MAC address.

Parameters
macEncoded MAC
hw_addrMAC address to fill in
Return values
rcReturn status code

Definition at line 82 of file acpimac.c.

82 {
83 int len;
84 int rc;
85
86 /* Attempt to base16-decode MAC address */
87 len = base16_decode ( mac, hw_addr, ETH_ALEN );
88 if ( len < 0 ) {
89 rc = len;
90 DBGC ( colour, "ACPI could not decode base16 MAC \"%s\": %s\n",
91 mac, strerror ( rc ) );
92 return rc;
93 }
94
95 return 0;
96}
#define colour
Colour for debug messages.
Definition acpi.c:42
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define DBGC(...)
Definition compiler.h:505
#define ETH_ALEN
Definition if_ether.h:9
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References colour, DBGC, ETH_ALEN, len, mac, rc, and strerror().

◆ acpimac_decode_raw()

int acpimac_decode_raw ( const char * mac,
uint8_t * hw_addr )
static

Decode raw MAC address.

Parameters
macEncoded MAC
hw_addrMAC address to fill in
Return values
rcReturn status code

Definition at line 105 of file acpimac.c.

105 {
106
107 memcpy ( hw_addr, mac, ETH_ALEN );
108 return 0;
109}
void * memcpy(void *dest, const void *src, size_t len) __nonnull

References ETH_ALEN, mac, and memcpy().

◆ acpimac_extract()

int acpimac_extract ( const struct acpi_header * zsdt,
size_t len,
size_t offset,
void * data,
struct acpimac_extractor * extractor )
static

Extract MAC address from DSDT/SSDT.

Parameters
zsdtDSDT or SSDT
lenLength of DSDT/SSDT
offsetOffset of signature within DSDT/SSDT
dataData buffer
extractorACPI MAC address extractor
Return values
rcReturn status code

Some vendors provide a "system MAC address" within the DSDT/SSDT, to be used to override the MAC address for a USB docking station.

A full implementation would require an ACPI bytecode interpreter, since at least one OEM allows the MAC address to be constructed by executable ACPI bytecode (rather than a fixed data structure).

We instead attempt to extract a plausible-looking "_AUXMAC_#.....#" string that appears shortly after an "AMAC" or "MACA" signature. This should work for most implementations encountered in practice.

Definition at line 146 of file acpimac.c.

148 {
149 size_t prefix_len = strlen ( extractor->prefix );
150 uint8_t *hw_addr = data;
151 size_t skip = 0;
152 char buf[ prefix_len + extractor->len + 1 /* "#" */ + 1 /* NUL */ ];
153 char *mac = &buf[prefix_len];
154 int rc;
155
156 /* Skip signature and at least one tag byte */
157 offset += ( 4 /* signature */ + 1 /* tag byte */ );
158
159 /* Scan for suitable string close to signature */
160 for ( skip = 0 ;
161 ( ( skip < ACPIMAC_MAX_SKIP ) &&
162 ( offset + skip + sizeof ( buf ) ) <= len ) ;
163 skip++ ) {
164
165 /* Read value */
166 memcpy ( buf, ( ( ( const void * ) zsdt ) + offset + skip ),
167 sizeof ( buf ) );
168
169 /* Check for expected format */
170 if ( memcmp ( buf, extractor->prefix, prefix_len ) != 0 )
171 continue;
172 if ( buf[ sizeof ( buf ) - 2 ] != '#' )
173 continue;
174 if ( buf[ sizeof ( buf ) - 1 ] != '\0' )
175 continue;
176 DBGC ( colour, "ACPI found MAC:\n" );
177 DBGC_HDA ( colour, ( offset + skip ), buf, sizeof ( buf ) );
178
179 /* Terminate MAC address string */
180 mac[extractor->len] = '\0';
181
182 /* Decode MAC address */
183 if ( ( rc = extractor->decode ( mac, hw_addr ) ) != 0 )
184 return rc;
185
186 /* Check MAC address validity */
187 if ( ! is_valid_ether_addr ( hw_addr ) ) {
188 DBGC ( colour, "ACPI has invalid MAC %s\n",
189 eth_ntoa ( hw_addr ) );
190 return -EINVAL;
191 }
192
193 return 0;
194 }
195
196 return -ENOENT;
197}
#define ACPIMAC_MAX_SKIP
Maximum number of bytes to skip after ACPI signature.
Definition acpimac.c:58
unsigned char uint8_t
Definition stdint.h:10
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint8_t data[48]
Additional event data.
Definition ena.h:11
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
static int is_valid_ether_addr(const void *addr)
Check if Ethernet address is valid.
Definition ethernet.h:78
#define DBGC_HDA(...)
Definition compiler.h:506
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
const char * prefix
Prefix string.
Definition acpimac.c:63
size_t len
Encoded MAC length.
Definition acpimac.c:65
int(* decode)(const char *mac, uint8_t *hw_addr)
Decode MAC.
Definition acpimac.c:72

References ACPIMAC_MAX_SKIP, colour, data, DBGC, DBGC_HDA, acpimac_extractor::decode, EINVAL, ENOENT, eth_ntoa(), is_valid_ether_addr(), acpimac_extractor::len, len, mac, memcmp(), memcpy(), offset, acpimac_extractor::prefix, rc, and strlen().

Referenced by acpimac_extract_auxmac(), and acpimac_extract_rtxmac().

◆ acpimac_extract_auxmac()

int acpimac_extract_auxmac ( const struct acpi_header * zsdt,
size_t len,
size_t offset,
void * data )
static

Extract "_AUXMAC_" MAC address from DSDT/SSDT.

Parameters
zsdtDSDT or SSDT
lenLength of DSDT/SSDT
offsetOffset of signature within DSDT/SSDT
dataData buffer
Return values
rcReturn status code

Definition at line 208 of file acpimac.c.

209 {
210
211 return acpimac_extract ( zsdt, len, offset, data, &acpimac_auxmac );
212}
static struct acpimac_extractor acpimac_auxmac
"_AUXMAC_" extraction mechanism
Definition acpimac.c:112
static int acpimac_extract(const struct acpi_header *zsdt, size_t len, size_t offset, void *data, struct acpimac_extractor *extractor)
Extract MAC address from DSDT/SSDT.
Definition acpimac.c:146

References acpimac_auxmac, acpimac_extract(), data, len, and offset.

Referenced by acpi_mac().

◆ acpimac_extract_rtxmac()

int acpimac_extract_rtxmac ( const struct acpi_header * zsdt,
size_t len,
size_t offset,
void * data )
static

Extract "_RTXMAC_" MAC address from DSDT/SSDT.

Parameters
zsdtDSDT or SSDT
lenLength of DSDT/SSDT
offsetOffset of signature within DSDT/SSDT
dataData buffer
Return values
rcReturn status code

Definition at line 223 of file acpimac.c.

224 {
225
226 return acpimac_extract ( zsdt, len, offset, data, &acpimac_rtxmac );
227}
static struct acpimac_extractor acpimac_rtxmac
"_RTXMAC_" extraction mechanism
Definition acpimac.c:119

References acpimac_extract(), acpimac_rtxmac, data, len, and offset.

Referenced by acpi_mac().

◆ acpi_mac()

int acpi_mac ( uint8_t * hw_addr)

Extract MAC address from DSDT/SSDT.

Parameters
hw_addrMAC address to fill in
Return values
rcReturn status code

Definition at line 235 of file acpimac.c.

235 {
236 int rc;
237
238 /* Look for an "AMAC" address */
239 if ( ( rc = acpi_extract ( AMAC_SIGNATURE, hw_addr,
240 acpimac_extract_auxmac ) ) == 0 )
241 return 0;
242
243 /* Look for a "MACA" address */
244 if ( ( rc = acpi_extract ( MACA_SIGNATURE, hw_addr,
245 acpimac_extract_auxmac ) ) == 0 )
246 return 0;
247
248 /* Look for a "RTMA" address */
249 if ( ( rc = acpi_extract ( RTMA_SIGNATURE, hw_addr,
250 acpimac_extract_rtxmac ) ) == 0 )
251 return 0;
252
253 return -ENOENT;
254}
int acpi_extract(uint32_t signature, void *data, int(*extract)(const struct acpi_header *zsdt, size_t len, size_t offset, void *data))
Extract value from DSDT/SSDT.
Definition acpi.c:228
#define RTMA_SIGNATURE
RTMA signature.
Definition acpimac.c:52
#define AMAC_SIGNATURE
AMAC signature.
Definition acpimac.c:46
static int acpimac_extract_auxmac(const struct acpi_header *zsdt, size_t len, size_t offset, void *data)
Extract "_AUXMAC_" MAC address from DSDT/SSDT.
Definition acpimac.c:208
static int acpimac_extract_rtxmac(const struct acpi_header *zsdt, size_t len, size_t offset, void *data)
Extract "_RTXMAC_" MAC address from DSDT/SSDT.
Definition acpimac.c:223
#define MACA_SIGNATURE
MACA signature.
Definition acpimac.c:49

References acpi_extract(), acpimac_extract_auxmac(), acpimac_extract_rtxmac(), AMAC_SIGNATURE, ENOENT, MACA_SIGNATURE, rc, and RTMA_SIGNATURE.

Referenced by ecm_fetch_mac(), sysmac_fetch(), and typeof().

◆ sysmac_fetch()

int sysmac_fetch ( void * data,
size_t len )
static

Fetch system MAC address setting.

Parameters
dataBuffer to fill with setting data
lenLength of buffer
Return values
lenLength of setting data, or negative error

Definition at line 263 of file acpimac.c.

263 {
265 int rc;
266
267 /* Try fetching ACPI MAC address */
268 if ( ( rc = acpi_mac ( mac ) ) != 0 )
269 return rc;
270
271 /* Return MAC address */
272 if ( len > sizeof ( mac ) )
273 len = sizeof ( mac );
274 memcpy ( data, mac, len );
275 return ( sizeof ( mac ) );
276}
int acpi_mac(uint8_t *hw_addr)
Extract MAC address from DSDT/SSDT.
Definition acpimac.c:235

References acpi_mac(), data, ETH_ALEN, len, mac, memcpy(), and rc.

◆ __setting()

const struct setting sysmac_setting __setting ( SETTING_MISC ,
sysmac  )

System MAC address setting.

References __setting, builtin_scope, and SETTING_MISC.

Variable Documentation

◆ acpimac_auxmac

struct acpimac_extractor acpimac_auxmac
static
Initial value:
= {
.prefix = "_AUXMAC_#",
.len = ( ETH_ALEN * 2 ),
}
static int acpimac_decode_base16(const char *mac, uint8_t *hw_addr)
Decode Base16-encoded MAC address.
Definition acpimac.c:82

"_AUXMAC_" extraction mechanism

Definition at line 112 of file acpimac.c.

112 {
113 .prefix = "_AUXMAC_#",
114 .len = ( ETH_ALEN * 2 ),
115 .decode = acpimac_decode_base16,
116};

Referenced by acpimac_extract_auxmac().

◆ acpimac_rtxmac

struct acpimac_extractor acpimac_rtxmac
static
Initial value:
= {
.prefix = "_RTXMAC_#",
.len = ETH_ALEN,
.decode = acpimac_decode_raw,
}
static int acpimac_decode_raw(const char *mac, uint8_t *hw_addr)
Decode raw MAC address.
Definition acpimac.c:105

"_RTXMAC_" extraction mechanism

Definition at line 119 of file acpimac.c.

119 {
120 .prefix = "_RTXMAC_#",
121 .len = ETH_ALEN,
122 .decode = acpimac_decode_raw,
123};

Referenced by acpimac_extract_rtxmac().

◆ __builtin_setting

struct builtin_setting sysmac_builtin_setting __builtin_setting
Initial value:
= {
.setting = &sysmac_setting,
.fetch = sysmac_fetch,
}
static int sysmac_fetch(void *data, size_t len)
Fetch system MAC address setting.
Definition acpimac.c:263

System MAC address built-in setting.

Definition at line 287 of file acpimac.c.

287 {
288 .setting = &sysmac_setting,
289 .fetch = sysmac_fetch,
290};