From 670503bb5233df2540e04d4455eb17d98a7bb0c1 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 4 May 2012 22:07:52 +0200 Subject: [PATCH] carl9170 firmware: add radar pattern generator This - rather large - patch includes parts of a future radar pattern generator which hopefully can be used for testing DFS without having to resort to expensive hardware. The basic concept has been successfully tested with p54 [firmware detector - easy to fool] . But, that does not mean it works with other devices just as well (or at all!). Note: This feature is WIP and it will not work out-of-the-box. Signed-off-by: Christian Lamparter --- autogen.sh | 6 ++ carlfw/Kconfig | 10 +++ carlfw/include/carl9170.h | 5 ++ carlfw/include/fwdsc.h | 3 + carlfw/include/radar.h | 157 ++++++++++++++++++++++++++++++++++++++ carlfw/include/timer.h | 5 ++ carlfw/src/fw.c | 13 +++- carlfw/src/main.c | 29 +++++++ include/shared/fwdesc.h | 23 ++++++ include/shared/version.h | 6 +- tools/.gitignore | 1 + tools/src/CMakeLists.txt | 2 +- tools/src/fwinfo.c | 21 +++++ tools/src/fwprepare.c | 157 ++++++++++++++++++++++++++++++++++++++ 14 files changed, 433 insertions(+), 5 deletions(-) create mode 100644 carlfw/include/radar.h create mode 100644 tools/src/fwprepare.c diff --git a/autogen.sh b/autogen.sh index 729041e..5d79159 100755 --- a/autogen.sh +++ b/autogen.sh @@ -33,6 +33,12 @@ case "$1" in tools/src/miniboot a carlfw/carl9170.fw minifw/miniboot.fw fi + + if [ "$CONFIG_CARL9170FW_BUILD_TOOLS" = "y" ]; then + echo -n "Prepare firmware image..." + tools/src/fwprepare carlfw/carl9170.fw + fi + sudo install -m 644 carlfw/carl9170.fw \ /lib/firmware/carl9170-$CONFIG_CARL9170FW_RELEASE_VERSION.fw echo "done." diff --git a/carlfw/Kconfig b/carlfw/Kconfig index f42268c..c2da51a 100644 --- a/carlfw/Kconfig +++ b/carlfw/Kconfig @@ -100,6 +100,16 @@ config CARL9170FW_EXPERIMENTAL def_bool y prompt "Experimental Features" +config CARL9170FW_RADAR + def_bool n + prompt "Radar pattern generator" + depends on CARL9170FW_EXPERIMENTAL + ---help--- + With this option enabled, the firmware can generate random + transmission pattern that might fool a reciever to believe + that there is an active radar on the channel. + Note: sadly, no SDR here. + config CARL9170FW_WOL_OPTION def_bool n prompt "Wakeup on WLAN" diff --git a/carlfw/include/carl9170.h b/carlfw/include/carl9170.h index d10a74e..df41f84 100644 --- a/carlfw/include/carl9170.h +++ b/carlfw/include/carl9170.h @@ -33,6 +33,7 @@ #include "dma.h" #include "usb.h" #include "cmd.h" +#include "radar.h" struct carl9170_bar_ctx { uint8_t ta[6]; @@ -142,6 +143,10 @@ struct firmware_context_struct { unsigned int ba_tail_idx, ba_head_idx, queued_ba; + + unsigned int soft_radar, + radar_last, + pattern_index; } wlan; struct { diff --git a/carlfw/include/fwdsc.h b/carlfw/include/fwdsc.h index 936bfed..6ae6563 100644 --- a/carlfw/include/fwdsc.h +++ b/carlfw/include/fwdsc.h @@ -35,6 +35,9 @@ struct carl9170_firmware_descriptor { struct carl9170fw_wol_desc wol; #endif /* CONFIG_CARL9170FW_WOL */ struct carl9170fw_motd_desc motd; +#ifdef CONFIG_CARL9170FW_RADAR + struct carl9170fw_radar_desc radar; +#endif /* CONFIG_CARL9170FW_RADAR */ struct carl9170fw_dbg_desc dbg; struct carl9170fw_last_desc last; } __packed; diff --git a/carlfw/include/radar.h b/carlfw/include/radar.h new file mode 100644 index 0000000..864882a --- /dev/null +++ b/carlfw/include/radar.h @@ -0,0 +1,157 @@ +/* + * carl9170 firmware - used by the ar9170 wireless device + * + * Radar pulse definitions + * + * Copyright 2012 Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __CARL9170FW_RADAR_H +#define __CARL9170FW_RADAR_H + +#include "generated/autoconf.h" +#include "types.h" +#include "compiler.h" +#include "fwdesc.h" + +enum RADAR_TYPE { + NO_RADAR = 0, + ONE_KHZ, + TEN_KHZ, + + ONE_TWO_KHZ, + + FCC1, + FCC4, + + ETSIFIXED, + + /* keep last */ + __CARL9170FW_NUM_RADARS +}; + +struct radar_info { + unsigned int pulses; + const struct radar_info_pattern *pattern; +}; + +struct radar_info_pattern { + unsigned int pulse_width; + unsigned int pulse_interval; + uint32_t pulse_pattern; + uint32_t pulse_mode; +}; + +static const struct radar_info_pattern radar_NO_RADAR[0] = { }; +static const struct radar_info_pattern radar_ONE_KHZ[] = { + { + .pulse_width = 1, + .pulse_interval = 1000, + .pulse_pattern = 0xa7438080, + .pulse_mode = 0x5f01, + }, +}; + +static const struct radar_info_pattern radar_TEN_KHZ[] = { + { + .pulse_width = 1, + .pulse_interval = 100, + .pulse_pattern = 0x436f0001, + .pulse_mode = 0x5f01, + }, +}; + +static const struct radar_info_pattern radar_ONE_TWO_KHZ[] = { + { + .pulse_width = 1, + .pulse_interval = 1000, + .pulse_pattern = 0xa7438080, + .pulse_mode = 0x5f01, + }, + + { + .pulse_width = 10, + .pulse_interval = 500, + .pulse_pattern = 0xa7431001, + .pulse_mode = 0x5f01, + }, +}; + +/* + * Data taken from: + * + */ + +/* FCC Test Signal 1 - 1us pulse, 1428 us interval */ +static const struct radar_info_pattern radar_FCC1[] = { + { + .pulse_width = 1, + .pulse_interval = 1428, + .pulse_pattern = 0xa7438080, + .pulse_mode = 0x5f01, + }, +}; + +/* FCC Test Signal 4 - 11-20us pulse, 200-500 us interval */ +static const struct radar_info_pattern radar_FCC4[] = { + { + .pulse_width = 11, + .pulse_interval = 200, + .pulse_pattern = 0xf3128008, + .pulse_mode = 0x5f01, + }, +}; + +/* ETSI Test Signal 1 (Fixed) - 1us Pulse, 750 us interval */ +static const struct radar_info_pattern radar_ETSIFIXED[] = { + { + .pulse_width = 1, + .pulse_interval = 750, + .pulse_pattern = 0x8a5f8080, + .pulse_mode = 0x5f01, + }, +}; + + +#define ADD_RADAR(name) [name] = { .pulses = ARRAY_SIZE(radar_## name), .pattern = radar_## name } + +static const struct radar_info radars[__CARL9170FW_NUM_RADARS] = { + ADD_RADAR(NO_RADAR), + ADD_RADAR(ONE_KHZ), + ADD_RADAR(TEN_KHZ), + ADD_RADAR(ONE_TWO_KHZ), + ADD_RADAR(FCC1), + ADD_RADAR(FCC4), + ADD_RADAR(ETSIFIXED), +}; + +#define MAP_ENTRY(idx) [idx] = { .index = idx, .name = # idx , } +#define NAMED_MAP_ENTRY(idx, named) [idx] = {.index = idx, .name = named, } + +static const struct carl9170fw_radar_map_entry radar_names[__CARL9170FW_NUM_RADARS] = { + MAP_ENTRY(NO_RADAR), + MAP_ENTRY(ONE_KHZ), + MAP_ENTRY(TEN_KHZ), + MAP_ENTRY(ONE_TWO_KHZ), + + MAP_ENTRY(FCC1), + MAP_ENTRY(FCC4), + + MAP_ENTRY(ETSIFIXED), +}; + +#endif /* __CARL9170FW_RADAR_H */ diff --git a/carlfw/include/timer.h b/carlfw/include/timer.h index 1c1c6cd..0464914 100644 --- a/carlfw/include/timer.h +++ b/carlfw/include/timer.h @@ -50,6 +50,11 @@ static inline __inline bool is_after_msecs(const uint32_t t0, const uint32_t mse return ((get_clock_counter() - t0) / 1000) > (msecs * fw.ticks_per_usec); } +static inline __inline bool is_after_usecs(const uint32_t t0, const uint32_t usecs) +{ + return ((get_clock_counter() - t0)) > (usecs * fw.ticks_per_usec); +} + /* * Note: Be careful with [u]delay. They won't service the * hardware watchdog timer. It might trigger if you diff --git a/carlfw/src/fw.c b/carlfw/src/fw.c index fde4a5d..c919141 100644 --- a/carlfw/src/fw.c +++ b/carlfw/src/fw.c @@ -65,6 +65,9 @@ const struct carl9170_firmware_descriptor __section(fwdsc) carl9170fw_desc = { #ifdef CONFIG_CARL9170FW_WOL BIT(CARL9170FW_WOL) | #endif /* CONFIG_CARL9170FW_WOL */ +#ifdef CONFIG_CARL9170FW_RADAR + BIT(CARL9170FW_RADAR_PATTERN_GENERATOR) | +#endif /* CONFIG_CARL9170FW_RADAR */ (0)), .miniboot_size = cpu_to_le16(0), @@ -90,7 +93,6 @@ const struct carl9170_firmware_descriptor __section(fwdsc) carl9170fw_desc = { ), #endif /* CONFIG_CARL9170FW_WOL */ - FILL(motd, MOTD, .fw_year_month_day = cpu_to_le32( CARL9170FW_SET_DAY(CARL9170FW_VERSION_DAY) + @@ -99,6 +101,15 @@ const struct carl9170_firmware_descriptor __section(fwdsc) carl9170fw_desc = { .desc = "Community AR9170 Linux", .release = CARL9170FW_VERSION_GIT), + +#ifdef CONFIG_CARL9170FW_RADAR + FILL(radar, RADAR, + .soft_radar = cpu_to_le32(&fw.wlan.soft_radar), + .num_radars = __CARL9170FW_NUM_RADARS, + .radars = { /* filled by the fwprepare tool */ }, + ), +#endif /* CONFIG_CARL9170FW_RADAR */ + FILL(dbg, DBG, .bogoclock_addr = cpu_to_le32(0), .counter_addr = cpu_to_le32(&fw.counter), diff --git a/carlfw/src/main.c b/carlfw/src/main.c index 17cbaf9..c35f5ad 100644 --- a/carlfw/src/main.c +++ b/carlfw/src/main.c @@ -31,6 +31,7 @@ #include "wl.h" #include "rf.h" #include "usb.h" +#include "radar.h" #define AR9170_WATCH_DOG_TIMER 0x100 @@ -185,6 +186,32 @@ static void tally_update(void) fw.counter++; } +static void radar_pattern_generator(void) +{ + if (fw.phy.state == CARL9170_PHY_ON) { + if (fw.wlan.soft_radar == NO_RADAR || + fw.wlan.soft_radar >= __CARL9170FW_NUM_RADARS) + return; + + const struct radar_info *radar = &radars[fw.wlan.soft_radar]; + if (radar->pulses >= fw.wlan.pattern_index) { + fw.wlan.pattern_index = 0; + } + + if (radar->pulses > fw.wlan.pattern_index) { + const struct radar_info_pattern *pattern = &radar->pattern[fw.wlan.pattern_index]; + if (is_after_usecs(fw.wlan.radar_last, pattern->pulse_interval)) { + fw.wlan.radar_last = get_clock_counter(); + //set(PATTERN, pattern->pulse_pattern); + //set(MODE, pattern->pulse_mode); + udelay(pattern->pulse_width); + //set(MODE, ~pattern->pulse_mode); + fw.wlan.pattern_index++; + } + } + } +} + static void __noreturn main_loop(void) { /* main loop */ @@ -204,6 +231,8 @@ static void __noreturn main_loop(void) handle_timer(); tally_update(); + + radar_pattern_generator(); } } diff --git a/include/shared/fwdesc.h b/include/shared/fwdesc.h index 6d9c089..903a346 100644 --- a/include/shared/fwdesc.h +++ b/include/shared/fwdesc.h @@ -78,6 +78,9 @@ enum carl9170fw_feature_list { /* HW (ANI, CCA, MIB) tally counters */ CARL9170FW_HW_COUNTERS, + /* Radar pattern generator */ + CARL9170FW_RADAR_PATTERN_GENERATOR, + /* KEEP LAST */ __CARL9170FW_FEATURE_NUM }; @@ -89,6 +92,7 @@ enum carl9170fw_feature_list { #define CHK_MAGIC "CHK\0" #define TXSQ_MAGIC "TXSQ" #define WOL_MAGIC "WOL\0" +#define RADAR_MAGIC "RDR\0" #define LAST_MAGIC "LAST" #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) @@ -173,6 +177,25 @@ struct carl9170fw_dbg_desc { #define CARL9170FW_DBG_DESC_SIZE \ (sizeof(struct carl9170fw_dbg_desc)) +#define CARL9170FW_RADAR_MAP_NAME_LEN 15 +struct carl9170fw_radar_map_entry { + u8 index; + char name[CARL9170FW_RADAR_MAP_NAME_LEN]; +} __packed; + +#define CARL9170FW_RADAR_DESC_MIN_VER 1 +#define CARL9170FW_RADAR_DESC_CUR_VER 1 +struct carl9170fw_radar_desc { + struct carl9170fw_desc_head head; + + __le32 soft_radar; + __le32 num_radars; + struct carl9170fw_radar_map_entry radars[0]; + /* Put your debugging definitions here */ +} __packed; +#define CARL9170FW_RADAR_DESC_SIZE \ + (sizeof(struct carl9170fw_radar_desc)) + #define CARL9170FW_CHK_DESC_MIN_VER 1 #define CARL9170FW_CHK_DESC_CUR_VER 2 struct carl9170fw_chk_desc { diff --git a/include/shared/version.h b/include/shared/version.h index 9fa241e..b6174e1 100644 --- a/include/shared/version.h +++ b/include/shared/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H #define CARL9170FW_VERSION_YEAR 12 -#define CARL9170FW_VERSION_MONTH 3 -#define CARL9170FW_VERSION_DAY 14 -#define CARL9170FW_VERSION_GIT "1.9.5" +#define CARL9170FW_VERSION_MONTH 4 +#define CARL9170FW_VERSION_DAY 22 +#define CARL9170FW_VERSION_GIT "1.9.5-2-g2bd700b" #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/tools/.gitignore b/tools/.gitignore index 6b99891..8fec132 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,6 +1,7 @@ src/checksum src/fwinfo src/miniboot +src/fwprepare src/eeprom_fix src/wol carlu/carlu diff --git a/tools/src/CMakeLists.txt b/tools/src/CMakeLists.txt index 3cd31fd..4605aa4 100644 --- a/tools/src/CMakeLists.txt +++ b/tools/src/CMakeLists.txt @@ -4,7 +4,7 @@ project(tools) add_custom_target(wol ALL COMMAND gcc wol.c -o wol) -set(tools fwinfo miniboot checksum eeprom_fix) +set(tools fwinfo miniboot checksum fwprepare eeprom_fix) foreach(tool ${tools}) add_executable( ${tool} ${tool}.c ) diff --git a/tools/src/fwinfo.c b/tools/src/fwinfo.c index 995e3ed..0f674f7 100644 --- a/tools/src/fwinfo.c +++ b/tools/src/fwinfo.c @@ -68,6 +68,7 @@ static const struct feature_list known_otus_features_v1[] = { CHECK_FOR_FEATURE(CARL9170FW_WOL), CHECK_FOR_FEATURE(CARL9170FW_FIXED_5GHZ_PSM), CHECK_FOR_FEATURE(CARL9170FW_HW_COUNTERS), + CHECK_FOR_FEATURE(CARL9170FW_RADAR_PATTERN_GENERATOR), }; static void check_feature_list(const struct carl9170fw_desc_head *head, @@ -206,6 +207,25 @@ static void show_chk_desc(const struct carl9170fw_desc_head *head, le32_to_cpu(chk->fw_crc32)); } +static void show_radar_desc(const struct carl9170fw_desc_head *head, + struct carlfw *fw __unused) +{ + const struct carl9170fw_radar_desc *radar = (const void *) head; + const struct carl9170fw_radar_map_entry *map = radar->radars; + int map_entries = (head->length - sizeof(*radar)) / sizeof(*map); + int i; + + fprintf(stdout, "\tRadar index register: %08x\n", + le32_to_cpu(radar->soft_radar)); + fprintf(stdout, "\tNumber of supported radar patterns: %08x\n", + le32_to_cpu(radar->num_radars)); + + for (i = 0; i < map_entries; i++) { + fprintf(stdout, "\t\tindex:0x%x, description:%s\n", + map[i].index, map[i].name); + } +} + static void show_last_desc(const struct carl9170fw_desc_head *head, struct carlfw *fw __unused) @@ -236,6 +256,7 @@ static const struct { ADD_HANDLER(FIX, show_fix_desc), ADD_HANDLER(CHK, show_chk_desc), ADD_HANDLER(WOL, show_wol_desc), + ADD_HANDLER(RADAR, show_radar_desc), ADD_HANDLER(LAST, show_last_desc), }; diff --git a/tools/src/fwprepare.c b/tools/src/fwprepare.c new file mode 100644 index 0000000..891dad2 --- /dev/null +++ b/tools/src/fwprepare.c @@ -0,0 +1,157 @@ +/* + * Copyright 2012 Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../carlfw/include/radar.h" +#include "carlfw.h" + +#include "compiler.h" + +static void checksum_help(void) +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\tfwprepare FW-FILE\n"); + + fprintf(stderr, "\nDescription:\n"); + fprintf(stderr, "\tThis simple utility prepares the firmware " + "for release.\n"); + + fprintf(stderr, "\nParameteres:\n"); + fprintf(stderr, "\t 'FW-FILE' = firmware name\n"); + fprintf(stderr, "\n"); +} + +static int add_radars(struct carlfw *fw) { + const struct carl9170fw_otus_desc *otus_desc = NULL; + struct carl9170fw_radar_desc *radar_desc = NULL; + int radars_to_add; + + otus_desc = carlfw_find_desc(fw, (uint8_t *) OTUS_MAGIC, + sizeof(*otus_desc), + CARL9170FW_OTUS_DESC_CUR_VER); + if (!otus_desc) { + fprintf(stderr, "No OTUS descriptor found\n"); + return -1; + } + + if (!carl9170fw_supports(otus_desc->feature_set, CARL9170FW_RADAR_PATTERN_GENERATOR)) { + return 0; + } + + radar_desc = carlfw_find_desc(fw, (uint8_t *) RADAR_MAGIC, + sizeof(*radar_desc), + CARL9170FW_RADAR_DESC_CUR_VER); + + if (!radar_desc) { + fprintf(stderr, "Firmware has radar pattern feature set, but " + "can't find a valid radar descriptor\n"); + } + + radars_to_add = radar_desc->num_radars - + ((radar_desc->head.length - sizeof(*radar_desc)) / + sizeof(struct carl9170fw_radar_map_entry)); + if (radars_to_add == 0) { + /* been there, done that */ + return 0; + } + + if (radars_to_add == __CARL9170FW_NUM_RADARS) { + struct carl9170fw_radar_desc *tmp; + unsigned int len, map_len; + + map_len = sizeof(struct carl9170fw_radar_map_entry) * radars_to_add; + len = sizeof(*tmp) + map_len; + tmp = malloc(len); + if (!tmp) + return -ENOMEM; + + radar_desc = carlfw_desc_mod_len(fw, &radar_desc->head, map_len); + if (IS_ERR_OR_NULL(radar_desc)) + return (int) PTR_ERR(radar_desc); + + memcpy(&radar_desc->radars, radar_names, map_len); + return 0; + } else { + fprintf(stderr, "don't know what you did, but congrats you broke it!"); + return -EINVAL; + } +} + +static int add_checksums(struct carlfw __unused *fw) +{ + /* + * No magic here, The checksum descriptor is added/update + * automatically in a subroutine of carlfw_store(). + */ + return 0; +} + +int main(int argc, char *args[]) +{ + struct carlfw *fw = NULL; + int err = 0; + + if (argc != 2) { + err = -EINVAL; + goto out; + } + + fw = carlfw_load(args[1]); + if (IS_ERR_OR_NULL(fw)) { + err = PTR_ERR(fw); + fprintf(stderr, "Failed to open file \"%s\" (%d).\n", + args[1], err); + goto out; + } + + err = add_radars(fw); + if (err) + goto out; + + err = add_checksums(fw); + if (err) + goto out; + + err = carlfw_store(fw); + if (err) { + fprintf(stderr, "Failed to apply checksum (%d).\n", err); + goto out; + } + +out: + switch (err) { + case 0: + fprintf(stdout, "firmware was prepared successfully.\n"); + break; + case -EINVAL: + checksum_help(); + break; + default: + break; + } + + carlfw_release(fw); + return err ? EXIT_FAILURE : EXIT_SUCCESS; +} -- 2.31.1