Skip to content

Instantly share code, notes, and snippets.

@BigNerd95
Last active December 5, 2021 14:36
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save BigNerd95/f06f14d46fa76ccaf519940592428c53 to your computer and use it in GitHub Desktop.
Save BigNerd95/f06f14d46fa76ccaf519940592428c53 to your computer and use it in GitHub Desktop.
Atheros ART bypass reading the modified dump from /etc/config/my_eeprom (the file must contain only the struct ar9300_eeprom [1088 bytes])
// Add these lines after the Copyright
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <linux/buffer_head.h>
// Copy these functions before ar9300_eeprom_restore_flash function
struct file *file_open(const char *path, int flags, int rights)
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
return NULL;
}
return filp;
}
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(KERNEL_DS);
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
void file_close(struct file *file)
{
filp_close(file, NULL);
}
bool read_eeprom_from_file(u8 *mptr, int mdata_size)
{
bool result = false;
struct file *fp = file_open("/etc/config/my_eeprom", O_RDONLY, 0);
if (fp > 0) {
printk(KERN_DEBUG "ath: Reading from FILE\n");
int tot = file_read(fp, fp->f_pos, mptr, mdata_size);
if (tot == mdata_size)
result = true;
file_close(fp);
printk(KERN_DEBUG "ath: Expected bytes: %d\n", mdata_size);
printk(KERN_DEBUG "ath: Read biyes: %d\n", tot);
}
return result;
}
static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr, int mdata_size) // mdata_size = sizeof(struct ar9300_eeprom)
{
u16 *data = (u16 *) mptr;
int i;
if (read_eeprom_from_file(mptr, mdata_size))
return 0;
printk(KERN_DEBUG "ath: Reading from EEPROM\n");
for (i = 0; i < mdata_size / 2; i++, data++)
if (!ath9k_hw_nvram_read(ah, i, data))
return -EIO;
return 0;
}
@BigNerd95
Copy link
Author

BigNerd95 commented Oct 4, 2017

LEDE instruction:

  1. Clone LEDE project
    git clone https://github.com/lede-project/source.git
    cd source

  2. Build for your target
    make menuconfig (select your target)
    make package/kernel/mac80211/compile

  3. Patch the driver with my diff
    You have to copy paste my code and comment the originial ar9300_eeprom_restore_flash function in this file:
    build_dir/target-[ARCH]/linux-ar71xx_generic/backports-[VER]/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
    Build again
    make -j9
    (Where 9 is your cpu's core number)

  4. Flash the router
    On PC: nc -l -p 1234 -q 0 < bin/targets/ar71xx/generic/lede-ar71xx-generic-[MODEL]-squashfs-sysupgrade.bin
    On router: nc 192.168.1.X 1234 > /tmp/fw.bin && sysupgrade /tmp/fw.bin

  5. Check the mod
    After the router reboot, check if my mod is running
    dmesg | grep ath
    You should see

ath: Reading from EEPROM
  1. Dump the EEPROM
    dd if=/dev/mtd4 of=/etc/config/my_eeprom bs=1 skip=4096 count=1088

  2. Patch the EEPROM dump
    Here I am setting the Australia Country Code
    echo -en "\x24\x80" | dd of=/etc/config/my_eeprom bs=1 count=2 seek=28 conv=notrunc
    (Numbers are in Little Endian)
    (0x24 is AU Country Code, 0x80 is a flag that indicates the driver to expect a Country Code and not a Regpair Map)
    reboot

  3. Check Reg Domain
    After the router reboot
    dmesg | grep ath
    You should see

ath: Reading from FILE
ath: Expected bytes: 1088
ath: Read biyes:     1088
ath: EEPROM regdomain: 0x8024
ath: Country alpha2 being used: AU

You can also request the reg domain
iw reg get
and you should see

global
country AU: DFS-ETSI
phy#1
country AU: DFS-ETSI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment