iPXE
Data Structures | Macros | Functions | Variables
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. More...
 
#define AMAC_SIGNATURE   ACPI_SIGNATURE ( 'A', 'M', 'A', 'C' )
 AMAC signature. More...
 
#define MACA_SIGNATURE   ACPI_SIGNATURE ( 'M', 'A', 'C', 'A' )
 MACA signature. More...
 
#define RTMA_SIGNATURE   ACPI_SIGNATURE ( 'R', 'T', 'M', 'A' )
 RTMA signature. More...
 
#define ACPIMAC_MAX_SKIP   8
 Maximum number of bytes to skip after ACPI signature. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static int acpimac_decode_base16 (const char *mac, uint8_t *hw_addr)
 Decode Base16-encoded MAC address. More...
 
static int acpimac_decode_raw (const char *mac, uint8_t *hw_addr)
 Decode raw MAC address. More...
 
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. More...
 
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. More...
 
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. More...
 
int acpi_mac (uint8_t *hw_addr)
 Extract MAC address from DSDT/SSDT. More...
 
static int sysmac_fetch (void *data, size_t len)
 Fetch system MAC address setting. More...
 
const struct setting sysmac_setting __setting (SETTING_MISC, sysmac)
 System MAC address setting. More...
 

Variables

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

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 42 of file acpimac.c.

◆ AMAC_SIGNATURE

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

AMAC signature.

Definition at line 45 of file acpimac.c.

◆ MACA_SIGNATURE

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

MACA signature.

Definition at line 48 of file acpimac.c.

◆ RTMA_SIGNATURE

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

RTMA signature.

Definition at line 51 of file acpimac.c.

◆ ACPIMAC_MAX_SKIP

#define ACPIMAC_MAX_SKIP   8

Maximum number of bytes to skip after ACPI signature.

This is entirely empirical.

Definition at line 57 of file acpimac.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ acpimac_decode_base16()

static 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 81 of file acpimac.c.

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

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

◆ acpimac_decode_raw()

static 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 104 of file acpimac.c.

104  {
105 
106  memcpy ( hw_addr, mac, ETH_ALEN );
107  return 0;
108 }
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define ETH_ALEN
Definition: if_ether.h:8

References ETH_ALEN, mac, and memcpy().

◆ acpimac_extract()

static 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 145 of file acpimac.c.

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

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()

static 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 207 of file acpimac.c.

208  {
209 
210  return acpimac_extract ( zsdt, len, offset, data, &acpimac_auxmac );
211 }
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:145
ring len
Length.
Definition: dwmac.h:231
static struct acpimac_extractor acpimac_auxmac
"_AUXMAC_" extraction mechanism
Definition: acpimac.c:111
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint16_t offset
Offset to command line.
Definition: bzimage.h:8

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

Referenced by acpi_mac().

◆ acpimac_extract_rtxmac()

static 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 222 of file acpimac.c.

223  {
224 
225  return acpimac_extract ( zsdt, len, offset, data, &acpimac_rtxmac );
226 }
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:145
ring len
Length.
Definition: dwmac.h:231
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static struct acpimac_extractor acpimac_rtxmac
"_RTXMAC_" extraction mechanism
Definition: acpimac.c:118
uint16_t offset
Offset to command line.
Definition: bzimage.h:8

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 234 of file acpimac.c.

234  {
235  int rc;
236 
237  /* Look for an "AMAC" address */
238  if ( ( rc = acpi_extract ( AMAC_SIGNATURE, hw_addr,
239  acpimac_extract_auxmac ) ) == 0 )
240  return 0;
241 
242  /* Look for a "MACA" address */
243  if ( ( rc = acpi_extract ( MACA_SIGNATURE, hw_addr,
244  acpimac_extract_auxmac ) ) == 0 )
245  return 0;
246 
247  /* Look for a "RTMA" address */
248  if ( ( rc = acpi_extract ( RTMA_SIGNATURE, hw_addr,
249  acpimac_extract_rtxmac ) ) == 0 )
250  return 0;
251 
252  return -ENOENT;
253 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
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:222
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:207
#define MACA_SIGNATURE
MACA signature.
Definition: acpimac.c:48
#define AMAC_SIGNATURE
AMAC signature.
Definition: acpimac.c:45
#define ENOENT
No such file or directory.
Definition: errno.h:514
#define RTMA_SIGNATURE
RTMA signature.
Definition: acpimac.c:51
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:227

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()

static 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 262 of file acpimac.c.

262  {
264  int rc;
265 
266  /* Try fetching ACPI MAC address */
267  if ( ( rc = acpi_mac ( mac ) ) != 0 )
268  return rc;
269 
270  /* Return MAC address */
271  if ( len > sizeof ( mac ) )
272  len = sizeof ( mac );
273  memcpy ( data, mac, len );
274  return ( sizeof ( mac ) );
275 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
void * memcpy(void *dest, const void *src, size_t len) __nonnull
int acpi_mac(uint8_t *hw_addr)
Extract MAC address from DSDT/SSDT.
Definition: acpimac.c:234
ring len
Length.
Definition: dwmac.h:231
unsigned char uint8_t
Definition: stdint.h:10
#define ETH_ALEN
Definition: if_ether.h:8
uint8_t data[48]
Additional event data.
Definition: ena.h:22

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.

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:81
#define ETH_ALEN
Definition: if_ether.h:8

"_AUXMAC_" extraction mechanism

Definition at line 111 of file acpimac.c.

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:104
#define ETH_ALEN
Definition: if_ether.h:8

"_RTXMAC_" extraction mechanism

Definition at line 118 of file acpimac.c.

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:262

System MAC address built-in setting.

Definition at line 286 of file acpimac.c.