Adding new, undocumented features into a kernel driver

Note: this is a recollection of my memory (and source files) from about 2 years ago AX88179 USB3 Ethernet device

How would I go about changing the MAC address (permanently) on this AX88179 USB 3.0 device without breaking it open?

I found myself with an unusual challenge - the MAC address of many networking devices, if not already burnt into One-Time Programmable memory, could possibly be stored in an external (rewritable) EEPROM. Breaking open the device and directly accessing the EEPROM would be trivial, however I was unwilling to scuff the glossy plastic enclosure; I sought to do this without dismantling the device.

Understanding the target: ASIX AX88179

EEPROM Layout

The first order of business is grabbing the datasheet to answer some preliminary questions:

After a loginwall, we have some preliminary answers:

The 41-page datasheet documents the AX88179 extremely well, however it was completely devoid of information pertaining to writing of the EEPROM. It seemed as though this was a sacred privilege reserved only for manufacturers : (

Can the drivers access the EEPROM?

AX88179 webpage

ASIX kindly offers a “non-blobby” Linux driver sources on their portal which builds flawlessly out of the box. Muchas gracias!

When initializing the device, the drivers require access to information such as the MAC address, and it may be possible that the device offers some EEPROM access during this phase. While there’s a good chance that the manufacturer might have already implemented a specific command to simply return the 6 bytes, one can still hope for direct EEPROM access!

AX88179 webpage

The ASIX driver interacts with the hardware mostly through passing commands to ax88179_read_cmd and ax88179_write_cmd, which are essentially read/write wrappers around usb_control_msg.

Within ax88179_178a.c lies a very interesting function access_eeprom_mac, which indeed directly accesses the EEPROM!

It seems that the key to writing the EEPROM is ax88179_write_cmd, with command AX_ACCESS_EEPROM with the desired data, followed by the AX_RELOAD_EEPROM_EFUSE command.

The curiously missing commands in the headers

AX88179 missingno? Where did the commands 0x07 and 0x08 go?

The ax88179_178a.h header lists the constants associated with its respective commands. Oddly, before the undocumented EFuse Enable/Disable, there seemed to be 2 missing commands. Could they be for EEPROM Enable/Disable? The chip itself did not appear to have a EEPROM write-protect pin, but it could have an internal flag to prevent spurious writes.

For good measure, I added these to the header:

#define AX_WRITE_EEPROM_EN 0x07

#define AX_WRITE_EEPROM_DIS 0x08

Kludging it all together

It’s an one-time use driver - the code doesn’t look good

ax88179_178a.c

Patch 1 eepromBytesToWrite contains the value to write (CA FE) - note the endianness. eepromWriteAddress for the write address. Inserted above ax88179_get_mac

Patch 2 In ax88179_bind, inserted above /* Get the MAC address */

ax88179_178a.h

Patch 3 Inserted between AX_RELOAD_EEPROM_EFUSE and AX_WRITE_EFUSE_EN

Using it

That’s it! EEPROM writes for a mortal. Remember to unload or blacklist any existing ax88179 drivers first before trying the patched driver!.


Apart from the MAC, I intended to change the Device/Manufacturer name too. It is super exciting to plug the device onto a fresh Windows PC and have it recognize “my” hardware. Now I can pass off as a NIC vendor :^)