Adding new, undocumented features into a kernel driver
Sat, May 27, 2017Note: this is a recollection of my memory (and source files) from about 2 years ago
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
The first order of business is grabbing the datasheet to answer some preliminary questions:
- Does it use an EEPROM?
- How is the EEPROM memory laid out? Any checksums?
- Can the EEPROM be written in-system, without external aid?
- Do they already offer a tool to modify the hardware MAC?
After a loginwall, we have some preliminary answers:
- Yes, it has an EEPROM, along with an OTP EFuse. A valid EEPROM takes precedence during initialization.
- First 6 bytes store the MAC Address. There’s also a checksum
- Although not explicitly stated, EEPROM can be written to without aid (during manufacturing).
- They have a Windows tool to configure and test devices during manufacturing. However it is unavailable for mere mortals like me (“please email sales”)
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?
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!
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!
- When
wflag
isfalse
, it tries to read the MAC, one byte at a time from the EEPROM, and setsdev->net->dev_addr
afterwards. - When
wflag
istrue
, it tries to write the MAC, one byte at a time to the EEPROM and waits for 15ms. It then reloads the new EEPROM data afterwards.
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
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
eepromBytesToWrite
contains the value to write (CA FE
) - note the endianness. eepromWriteAddress
for the write address. Inserted above ax88179_get_mac
In ax88179_bind
, inserted above /* Get the MAC address */
ax88179_178a.h
Inserted between AX_RELOAD_EEPROM_EFUSE
and AX_WRITE_EFUSE_EN
Using it
make
should happily emit aax88179_178a.ko
.insmod ax88179_178a.ko
to load the driver, writing the EEPROMrmmod ax88179_178a
to unload the driverdmesg
to check if it worked! It should hopefully contain a “eeprom write completed”
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 :^)