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 (userptr_t 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 (userptr_t zsdt, size_t len, size_t offset, void *data)
 Extract "_AUXMAC_" MAC address from DSDT/SSDT. More...
 
static int acpimac_extract_rtxmac (userptr_t 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
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
uint32_t len
Length.
Definition: ena.h:14

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 ( userptr_t  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.

146  {
147  size_t prefix_len = strlen ( extractor->prefix );
148  uint8_t *hw_addr = data;
149  size_t skip = 0;
150  char buf[ prefix_len + extractor->len + 1 /* "#" */ + 1 /* NUL */ ];
151  char *mac = &buf[prefix_len];
152  int rc;
153 
154  /* Skip signature and at least one tag byte */
155  offset += ( 4 /* signature */ + 1 /* tag byte */ );
156 
157  /* Scan for suitable string close to signature */
158  for ( skip = 0 ;
159  ( ( skip < ACPIMAC_MAX_SKIP ) &&
160  ( offset + skip + sizeof ( buf ) ) <= len ) ;
161  skip++ ) {
162 
163  /* Read value */
164  copy_from_user ( buf, zsdt, ( offset + skip ),
165  sizeof ( buf ) );
166 
167  /* Check for expected format */
168  if ( memcmp ( buf, extractor->prefix, prefix_len ) != 0 )
169  continue;
170  if ( buf[ sizeof ( buf ) - 2 ] != '#' )
171  continue;
172  if ( buf[ sizeof ( buf ) - 1 ] != '\0' )
173  continue;
174  DBGC ( colour, "ACPI found MAC:\n" );
175  DBGC_HDA ( colour, ( offset + skip ), buf, sizeof ( buf ) );
176 
177  /* Terminate MAC address string */
178  mac[extractor->len] = '\0';
179 
180  /* Decode MAC address */
181  if ( ( rc = extractor->decode ( mac, hw_addr ) ) != 0 )
182  return rc;
183 
184  /* Check MAC address validity */
185  if ( ! is_valid_ether_addr ( hw_addr ) ) {
186  DBGC ( colour, "ACPI has invalid MAC %s\n",
187  eth_ntoa ( hw_addr ) );
188  return -EINVAL;
189  }
190 
191  return 0;
192  }
193 
194  return -ENOENT;
195 }
#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
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
#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
#define DBGC_HDA(...)
Definition: compiler.h:506
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#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
uint32_t len
Length.
Definition: ena.h:14
uint8_t data[48]
Additional event data.
Definition: ena.h:22
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114

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

Referenced by acpimac_extract_auxmac(), and acpimac_extract_rtxmac().

◆ acpimac_extract_auxmac()

static int acpimac_extract_auxmac ( userptr_t  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 206 of file acpimac.c.

207  {
208 
209  return acpimac_extract ( zsdt, len, offset, data, &acpimac_auxmac );
210 }
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static int acpimac_extract(userptr_t zsdt, size_t len, size_t offset, void *data, struct acpimac_extractor *extractor)
Extract MAC address from DSDT/SSDT.
Definition: acpimac.c:145
uint32_t len
Length.
Definition: ena.h:14
static struct acpimac_extractor acpimac_auxmac
"_AUXMAC_" extraction mechanism
Definition: acpimac.c:111
uint8_t data[48]
Additional event data.
Definition: ena.h:22

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

Referenced by acpi_mac().

◆ acpimac_extract_rtxmac()

static int acpimac_extract_rtxmac ( userptr_t  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 221 of file acpimac.c.

222  {
223 
224  return acpimac_extract ( zsdt, len, offset, data, &acpimac_rtxmac );
225 }
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static int acpimac_extract(userptr_t zsdt, size_t len, size_t offset, void *data, struct acpimac_extractor *extractor)
Extract MAC address from DSDT/SSDT.
Definition: acpimac.c:145
uint32_t len
Length.
Definition: ena.h:14
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static struct acpimac_extractor acpimac_rtxmac
"_RTXMAC_" extraction mechanism
Definition: acpimac.c:118

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

233  {
234  int rc;
235 
236  /* Look for an "AMAC" address */
237  if ( ( rc = acpi_extract ( AMAC_SIGNATURE, hw_addr,
238  acpimac_extract_auxmac ) ) == 0 )
239  return 0;
240 
241  /* Look for a "MACA" address */
242  if ( ( rc = acpi_extract ( MACA_SIGNATURE, hw_addr,
243  acpimac_extract_auxmac ) ) == 0 )
244  return 0;
245 
246  /* Look for a "RTMA" address */
247  if ( ( rc = acpi_extract ( RTMA_SIGNATURE, hw_addr,
248  acpimac_extract_rtxmac ) ) == 0 )
249  return 0;
250 
251  return -ENOENT;
252 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#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
static int acpimac_extract_auxmac(userptr_t zsdt, size_t len, size_t offset, void *data)
Extract "_AUXMAC_" MAC address from DSDT/SSDT.
Definition: acpimac.c:206
int acpi_extract(uint32_t signature, void *data, int(*extract)(userptr_t zsdt, size_t len, size_t offset, void *data))
Extract value from DSDT/SSDT.
Definition: acpi.c:240
#define RTMA_SIGNATURE
RTMA signature.
Definition: acpimac.c:51
static int acpimac_extract_rtxmac(userptr_t zsdt, size_t len, size_t offset, void *data)
Extract "_RTXMAC_" MAC address from DSDT/SSDT.
Definition: acpimac.c:221

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

261  {
263  int rc;
264 
265  /* Try fetching ACPI MAC address */
266  if ( ( rc = acpi_mac ( mac ) ) != 0 )
267  return rc;
268 
269  /* Return MAC address */
270  if ( len > sizeof ( mac ) )
271  len = sizeof ( mac );
272  memcpy ( data, mac, len );
273  return ( sizeof ( mac ) );
274 }
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:233
unsigned char uint8_t
Definition: stdint.h:10
#define ETH_ALEN
Definition: if_ether.h:8
uint32_t len
Length.
Definition: ena.h:14
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:261

System MAC address built-in setting.

Definition at line 285 of file acpimac.c.