├── patch.ld
├── LICENSE
├── src
├── version.c
├── patch.c
├── debugger.c
└── debugger_base.c
├── README.md
└── Makefile
/patch.ld:
--------------------------------------------------------------------------------
1 | MEMORY
2 | {
3 | INCLUDE gen/memory.ld
4 | }
5 |
6 | SECTIONS
7 | {
8 | INCLUDE gen/flashpatches.ld
9 | INCLUDE gen/nexmon.ld
10 | }
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | ########### ########### ########## ##########
3 | ############ ############ ############ ############
4 | ## ## ## ## ## ## ##
5 | ## ## ## ## ## ## ##
6 | ########### #### ###### ## ## ## ## ######
7 | ########### #### # ## ## ## ## # #
8 | ## ## ###### ## ## ## ## # #
9 | ## ## # ## ## ## ## # #
10 | ############ ##### ###### ## ## ## ##### ######
11 | ########### ########### ## ## ## ##########
12 |
13 | S E C U R E M O B I L E N E T W O R K I N G
14 |
15 | License:
16 |
17 | Copyright (c) 2017 Secure Mobile Networking Lab (SEEMOO)
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a
20 | copy of this software and associated documentation files (the
21 | "Software"), to deal in the Software without restriction, including
22 | without limitation the rights to use, copy, modify, merge, publish,
23 | distribute, sublicense, and/or sell copies of the Software, and to
24 | permit persons to whom the Software is furnished to do so, subject to
25 | the following conditions:
26 |
27 | 1. The above copyright notice and this permission notice shall be
28 | include in all copies or substantial portions of the Software.
29 |
30 | 2. Any use of the Software which results in an academic publication or
31 | other publication which includes a bibliography must include
32 | citations to the nexmon project a):
33 |
34 | a) "Matthias Schulz, Daniel Wegemer and Matthias Hollick. Nexmon:
35 | The C-based Firmware Patching Framework. https://nexmon.org"
36 |
37 | 3. The Software is not used by, in cooperation with, or on behalf of
38 | any armed forces, intelligence agencies, reconnaissance agencies,
39 | defense agencies, offense agencies or any supplier, contractor, or
40 | research associated.
41 |
42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
43 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 |
--------------------------------------------------------------------------------
/src/version.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | * *
3 | * ########### ########### ########## ########## *
4 | * ############ ############ ############ ############ *
5 | * ## ## ## ## ## ## ## *
6 | * ## ## ## ## ## ## ## *
7 | * ########### #### ###### ## ## ## ## ###### *
8 | * ########### #### # ## ## ## ## # # *
9 | * ## ## ###### ## ## ## ## # # *
10 | * ## ## # ## ## ## ## # # *
11 | * ############ ##### ###### ## ## ## ##### ###### *
12 | * ########### ########### ## ## ## ########## *
13 | * *
14 | * S E C U R E M O B I L E N E T W O R K I N G *
15 | * *
16 | * This file is part of NexMon. *
17 | * *
18 | * Copyright (c) 2016 NexMon Team *
19 | * *
20 | * NexMon is free software: you can redistribute it and/or modify *
21 | * it under the terms of the GNU General Public License as published by *
22 | * the Free Software Foundation, either version 3 of the License, or *
23 | * (at your option) any later version. *
24 | * *
25 | * NexMon is distributed in the hope that it will be useful, *
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 | * GNU General Public License for more details. *
29 | * *
30 | * You should have received a copy of the GNU General Public License *
31 | * along with NexMon. If not, see . *
32 | * *
33 | **************************************************************************/
34 |
35 | #pragma NEXMON targetregion "patch"
36 |
37 | #include // definition of firmware version macros
38 | #include // macros used to craete patches such as BLPatch, BPatch, ...
39 |
40 | char version[] = "nexmon_ver: " GIT_VERSION "-" BUILD_NUMBER "\n";
41 |
42 | __attribute__((at(0x1F2470, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
43 | GenericPatch4(version_patch, version);
44 |
--------------------------------------------------------------------------------
/src/patch.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | * *
3 | * ########### ########### ########## ########## *
4 | * ############ ############ ############ ############ *
5 | * ## ## ## ## ## ## ## *
6 | * ## ## ## ## ## ## ## *
7 | * ########### #### ###### ## ## ## ## ###### *
8 | * ########### #### # ## ## ## ## # # *
9 | * ## ## ###### ## ## ## ## # # *
10 | * ## ## # ## ## ## ## # # *
11 | * ############ ##### ###### ## ## ## ##### ###### *
12 | * ########### ########### ## ## ## ########## *
13 | * *
14 | * S E C U R E M O B I L E N E T W O R K I N G *
15 | * *
16 | * This file is part of NexMon. *
17 | * *
18 | * Copyright (c) 2016 NexMon Team *
19 | * *
20 | * NexMon is free software: you can redistribute it and/or modify *
21 | * it under the terms of the GNU General Public License as published by *
22 | * the Free Software Foundation, either version 3 of the License, or *
23 | * (at your option) any later version. *
24 | * *
25 | * NexMon is distributed in the hope that it will be useful, *
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 | * GNU General Public License for more details. *
29 | * *
30 | * You should have received a copy of the GNU General Public License *
31 | * along with NexMon. If not, see . *
32 | * *
33 | **************************************************************************/
34 |
35 | #pragma NEXMON targetregion "patch"
36 |
37 | #include // definition of firmware version macros
38 | #include // contains macros to access the debug hardware
39 | #include // wrapper definitions for functions that already exist in the firmware
40 | #include // structures that are used by the code in the firmware
41 | #include // useful helper functions
42 | #include // macros used to craete patches such as BLPatch, BPatch, ...
43 | #include // rates used to build the ratespec for frame injection
44 | #include // capabilities included in a nexmon patch
45 |
46 | int capabilities = NEX_CAP_MONITOR_MODE | NEX_CAP_MONITOR_MODE_RADIOTAP | NEX_CAP_FRAME_INJECTION;
47 |
48 | // Hook the call to wlc_ucode_write in wlc_ucode_download
49 | __attribute__((at(0x1F4F08, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_40_r581243)))
50 | __attribute__((at(0x1F4F14, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
51 | BLPatch(wlc_ucode_write_compressed, wlc_ucode_write_compressed);
52 |
53 | // reduce the amount of ucode memory freed to become part of the heap
54 | __attribute__((at(0x1816E0, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
55 | GenericPatch4(hndrte_reclaim_0_end, PATCHSTART);
56 |
57 | extern unsigned char templateram_bin[];
58 |
59 | // Moving template ram to another place in the ucode region
60 | __attribute__((at(0x185544, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
61 | GenericPatch4(templateram_bin, templateram_bin);
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Nexmon Debugger
4 |
5 | To analyze the FullMAC firmware running on the ARM microcontroller in the BCM4339 Wi-Fi chip,
6 | we created a debugger in software that directly accesses the hardware registers of the ARM
7 | Debugging core. As we do not have access to the JTAG port, we generate exceptions whenever a
8 | breakpoint or watchpoint is triggered. We handle those exceptions in our firmware patch and
9 | can then continue with the execution of the firmware code.
10 |
11 | In our example, we set a breakpoint at the `printf` function:
12 | ```
13 | dbg_set_breakpoint_for_addr_match(0, 0x126f0); // trigger on printf
14 | ```
15 | When it triggers, the function `handle_pref_abort_exception` is called. There, we check if
16 | register `R1` points to the string `sdpcmd_dpc`. If the condition matches, we print a debug
17 | message and activate single-step debugging. To this end, we set the breakpoint to trigger on
18 | a mismatch of the address of the current program counter. Then we can decide to either trigger
19 | on a mismatch of the current program counter address again for single stepping or reset the
20 | breakpoint to the original address of the `printf` funciton.
21 |
22 | Additionally, we set a memory watchpoint on the address of the string
23 | `%s: Broadcom SDPCMD CDC driver`:
24 | ```
25 | dbg_set_watchpoint_for_addr_match(0, 0x1FC2A4); // trigger on "%s: Broadcom SDPCMD CDC driver" string
26 | ```
27 | Whenever, code reads or writes to this address, a data abort exception is triggered that is
28 | handled by the `handle_data_abort_exception` function. In this function, we print the address
29 | of the instruction accessing monitored memory location. We also disable the watchpoint and set
30 | a new breakpoint to trigger on an address mismatch of the current program counter to advance
31 | by one instruction. The breakpoint handler reactivates the watchpoint.
32 |
33 | The output observed on the console is as follows:
34 | ```
35 | start=0x001eb5d8 len=0x00000800
36 |
37 | RTE (USB-SDIO-CDC) 6.37.32.RC23.34.43 (r639704) on BCM4339 r1 @ 37.4/161.3/161.3MHz
38 | 000000.010 WP hit pc=00012b3a
39 | 000000.013 WP hit pc=00012b3a
40 | 000000.010 sdpcmdcdc0: Broadcom SDPCMD CDC driver
41 | 000000.141 reclaim section 0: Returned 31688 bytes to the heap
42 | 000000.189 nexmon_ver: 63fb-dirty-14
43 | 000000.192 wl_nd_ra_filter_init: Enter..
44 | 000000.196 TCAM: 256 used: 198 exceed:0
45 | 000000.200 WP hit pc=000126c2
46 | 000000.203 reclaim section 1: Returned 71844 bytes to the heap
47 | 000000.208 BP0 step 0: pc=000126f0 *r1=sdpcmd_dpc
48 | 000000.213 BP0 step 1: pc=000126f2
49 | 000000.216 BP0 step 2: pc=000126f4
50 | 000000.219 BP0 step 3: pc=000126f6
51 | 000000.223 BP0 step 4: pc=000126fa
52 | 000000.226 BP0 single-stepping done
53 | 000000.229 sdpcmd_dpc: Enable
54 | 000000.234 wl0: wlc_bmac_ucodembss_hwcap: Insuff mem for MBSS: templ memblks 192 fifo memblks 259
55 | 000000.249 wl0: wlc_enable_probe_req: state down, deferring setting of host flags
56 | 000000.295 wl0: wlc_enable_probe_req: state down, deferring setting of host flags
57 | 000000.303 wl0: wlc_enable_probe_req: state down, deferring setting of host flags
58 | ```
59 |
60 | `0x12b3a` is an instruction in the `vsnprintf` function called during the `printf` call writing to
61 | the chip's console. `0x126c2` is an instruction in the `memset` function, called after initialization
62 | when parts of the code used during initialization is freed and assigned to the heap.
63 |
64 | # Extract from our License
65 |
66 | Any use of the Software which results in an academic publication or
67 | other publication which includes a bibliography must include
68 | citations to the nexmon project (1):
69 |
70 | 1. "Matthias Schulz, Daniel Wegemer and Matthias Hollick. Nexmon:
71 | The C-based Firmware Patching Framework. https://nexmon.org"
72 |
73 | # Getting Started
74 |
75 | To compile the source code, you are required to first checkout a copy of the original nexmon
76 | repository that contains our C-based patching framework for Wi-Fi firmwares. That you checkout
77 | this repository as one of the sub-projects in the corresponding patches sub-directory. This
78 | allows you to build and compile all the firmware patches required to repeat our experiments.
79 | The following steps will get you started on Xubuntu 16.04 LTS:
80 |
81 | 1. Install some dependencies: `sudo apt-get install git gawk qpdf adb`
82 | 2. **Only necessary for x86_64 systems**, install i386 libs:
83 |
84 | ```
85 | sudo dpkg --add-architecture i386
86 | sudo apt-get update
87 | sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
88 | ```
89 | 3. Clone the nexmon base repository: `git clone https://github.com/seemoo-lab/nexmon.git`.
90 | 4. Download and extract Android NDK r11c (use exactly this version!).
91 | 5. Export the NDK_ROOT environment variable pointing to the location where you extracted the ndk so that it can be found by our build environment.
92 | 6. Navigate to the previously cloned nexmon directory and execute `source setup_env.sh` to set a couple of environment variables.
93 | 7. Run `make` to extract ucode, templateram and flashpatches from the original firmwares.
94 | 8. Navigate to utilities and run `make` to build all utilities such as nexmon.
95 | 9. Attach your rooted Nexus 5 smartphone running stock firmware version 6.0.1 (M4B30Z, Dec 2016).
96 | 10. Run `make install` to install all the built utilities on your phone.
97 | 11. Navigate to patches/bcm4339/6_37_34_43/ and clone this repository: `git clone https://github.com/seemoo-lab/wintech2017_nexmon_ping_offloading.git`
98 | 12. Enter the created subdirectory wisec2017_nexmon_jammer and run `make install-firmware` to compile our firmware patch and install it on the attached Nexus 5 smartphone.
99 |
100 | # References
101 |
102 | * Matthias Schulz, Daniel Wegemer and Matthias Hollick. **Nexmon: The C-based Firmware Patching Framework**. https://nexmon.org
103 |
104 | [Get references as bibtex file](https://nexmon.org/bib)
105 |
106 | # Contact
107 |
108 | * [Matthias Schulz](https://seemoo.tu-darmstadt.de/mschulz)
109 |
110 | # Powered By
111 |
112 | ## Secure Mobile Networking Lab (SEEMOO)
113 | 
114 | ## Networked Infrastructureless Cooperation for Emergency Response (NICER)
115 | 
116 | ## Multi-Mechanisms Adaptation for the Future Internet (MAKI)
117 | 
118 | ## Technische Universität Darmstadt
119 | 
120 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
2 | include ../version.mk
3 | include $(FW_PATH)/definitions.mk
4 |
5 | LOCAL_SRCS=$(wildcard src/*.c) src/ucode_compressed.c src/templateram.c
6 | COMMON_SRCS=$(wildcard $(NEXMON_ROOT)/patches/common/*.c)
7 | FW_SRCS=$(wildcard $(FW_PATH)/*.c)
8 |
9 | OBJS=$(addprefix obj/,$(notdir $(LOCAL_SRCS:.c=.o)) $(notdir $(COMMON_SRCS:.c=.o)) $(notdir $(FW_SRCS:.c=.o)))
10 |
11 | CFLAGS= \
12 | -fplugin=$(CCPLUGIN) \
13 | -fplugin-arg-nexmon-objfile=$@ \
14 | -fplugin-arg-nexmon-prefile=gen/nexmon.pre \
15 | -fplugin-arg-nexmon-chipver=$(NEXMON_CHIP_NUM) \
16 | -fplugin-arg-nexmon-fwver=$(NEXMON_FW_VERSION_NUM) \
17 | -fno-strict-aliasing \
18 | -DNEXMON_CHIP=$(NEXMON_CHIP) \
19 | -DNEXMON_FW_VERSION=$(NEXMON_FW_VERSION) \
20 | -DPATCHSTART=$(PATCHSTART) \
21 | -DUCODESIZE=$(UCODESIZE) \
22 | -DGIT_VERSION=\"$(GIT_VERSION)\" \
23 | -DBUILD_NUMBER=\"$$(cat BUILD_NUMBER)\" \
24 | -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -march=$(NEXMON_ARCH) \
25 | -ffunction-sections -fdata-sections \
26 | -I$(NEXMON_ROOT)/patches/include \
27 | -Iinclude \
28 | -I$(FW_PATH)
29 |
30 | all: fw_bcmdhd.bin
31 |
32 | init: FORCE
33 | $(Q)if ! test -f BUILD_NUMBER; then echo 0 > BUILD_NUMBER; fi
34 | $(Q)echo $$(($$(cat BUILD_NUMBER) + 1)) > BUILD_NUMBER
35 | $(Q)touch src/version.c
36 | $(Q)make -s -f $(NEXMON_ROOT)/patches/common/header.mk
37 | @printf "\033[0;31m CREATING DIRECTORIES\033[0m obj, gen, log\n"
38 | $(Q)mkdir -p obj gen log
39 |
40 | obj/%.o: src/%.c
41 | @printf "\033[0;31m COMPILING\033[0m %s => %s (details: log/compiler.log)\n" $< $@
42 | $(Q)cat gen/nexmon.pre 2>>log/error.log | gawk '{ if ($$3 != "$@") print; }' > tmp && mv tmp gen/nexmon.pre
43 | $(Q)$(CC)gcc $(CFLAGS) -c $< -o $@ >>log/compiler.log
44 |
45 | obj/%.o: $(NEXMON_ROOT)/patches/common/%.c
46 | @printf "\033[0;31m COMPILING\033[0m %s => %s (details: log/compiler.log)\n" $< $@
47 | $(Q)cat gen/nexmon.pre 2>>log/error.log | gawk '{ if ($$3 != "$@") print; }' > tmp && mv tmp gen/nexmon.pre
48 | $(Q)$(CC)gcc $(CFLAGS) -c $< -o $@ >>log/compiler.log
49 |
50 | obj/%.o: $(FW_PATH)/%.c
51 | @printf "\033[0;31m COMPILING\033[0m %s => %s (details: log/compiler.log)\n" $< $@
52 | $(Q)cat gen/nexmon.pre 2>>log/error.log | gawk '{ if ($$3 != "$@") print; }' > tmp && mv tmp gen/nexmon.pre
53 | $(Q)$(CC)gcc $(CFLAGS) -c $< -o $@ >>log/compiler.log
54 |
55 | gen/nexmon2.pre: $(OBJS)
56 | @printf "\033[0;31m PREPARING\033[0m %s => %s\n" "gen/nexmon.pre" $@
57 | $(Q)cat gen/nexmon.pre | awk '{ if ($$3 != "obj/flashpatches.o" && $$3 != "obj/wrapper.o") { print $$0; } }' > tmp
58 | $(Q)cat gen/nexmon.pre | awk '{ if ($$3 == "obj/flashpatches.o" || $$3 == "obj/wrapper.o") { print $$0; } }' >> tmp
59 | $(Q)cat tmp | awk '{ if ($$1 ~ /^0x/) { if ($$3 != "obj/flashpatches.o" && $$3 != "obj/wrapper.o") { if (!x[$$1]++) { print $$0; } } else { if (!x[$$1]) { print $$0; } } } else { print $$0; } }' > gen/nexmon2.pre
60 |
61 | gen/nexmon.ld: gen/nexmon2.pre $(OBJS)
62 | @printf "\033[0;31m GENERATING LINKER FILE\033[0m gen/nexmon.pre => %s\n" $@
63 | $(Q)sort gen/nexmon2.pre | gawk -f $(NEXMON_ROOT)/buildtools/scripts/nexmon.ld.awk > $@
64 |
65 | gen/nexmon.mk: gen/nexmon2.pre $(OBJS) $(FW_PATH)/definitions.mk
66 | @printf "\033[0;31m GENERATING MAKE FILE\033[0m gen/nexmon.pre => %s\n" $@
67 | $(Q)printf "fw_bcmdhd.bin: gen/patch.elf FORCE\n" > $@
68 | $(Q)sort gen/nexmon2.pre | \
69 | gawk -v src_file=gen/patch.elf -f $(NEXMON_ROOT)/buildtools/scripts/nexmon.mk.1.awk | \
70 | gawk -v ramstart=$(RAMSTART) -f $(NEXMON_ROOT)/buildtools/scripts/nexmon.mk.2.awk >> $@
71 | $(Q)printf "\nFORCE:\n" >> $@
72 | $(Q)gawk '!a[$$0]++' $@ > tmp && mv tmp $@
73 |
74 | gen/flashpatches.ld: gen/nexmon2.pre $(OBJS)
75 | @printf "\033[0;31m GENERATING LINKER FILE\033[0m gen/nexmon.pre => %s\n" $@
76 | $(Q)sort gen/nexmon2.pre | \
77 | gawk -f $(NEXMON_ROOT)/buildtools/scripts/flashpatches.ld.awk > $@
78 |
79 | gen/flashpatches.mk: gen/nexmon2.pre $(OBJS) $(FW_PATH)/definitions.mk
80 | @printf "\033[0;31m GENERATING MAKE FILE\033[0m gen/nexmon.pre => %s\n" $@
81 | $(Q)cat gen/nexmon2.pre | gawk \
82 | -v fp_data_base=$(FP_DATA_BASE) \
83 | -v fp_config_base=$(FP_CONFIG_BASE) \
84 | -v fp_data_end_ptr=$(FP_DATA_END_PTR) \
85 | -v fp_config_base_ptr_1=$(FP_CONFIG_BASE_PTR_1) \
86 | -v fp_config_end_ptr_1=$(FP_CONFIG_END_PTR_1) \
87 | -v fp_config_base_ptr_2=$(FP_CONFIG_BASE_PTR_2) \
88 | -v fp_config_end_ptr_2=$(FP_CONFIG_END_PTR_2) \
89 | -v ramstart=$(RAMSTART) \
90 | -v out_file=fw_bcmdhd.bin \
91 | -v src_file=gen/patch.elf \
92 | -f $(NEXMON_ROOT)/buildtools/scripts/flashpatches.mk.awk > $@
93 |
94 | gen/memory.ld: $(FW_PATH)/definitions.mk
95 | @printf "\033[0;31m GENERATING LINKER FILE\033[0m %s\n" $@
96 | $(Q)printf "rom : ORIGIN = 0x%08x, LENGTH = 0x%08x\n" $(ROMSTART) $(ROMSIZE) > $@
97 | $(Q)printf "ram : ORIGIN = 0x%08x, LENGTH = 0x%08x\n" $(RAMSTART) $(RAMSIZE) >> $@
98 | $(Q)printf "patch : ORIGIN = 0x%08x, LENGTH = 0x%08x\n" $(PATCHSTART) $(PATCHSIZE) >> $@
99 | $(Q)printf "ucode : ORIGIN = 0x%08x, LENGTH = 0x%08x\n" $(UCODESTART) $$(($(FP_CONFIG_BASE) - $(UCODESTART))) >> $@
100 | $(Q)printf "fpconfig : ORIGIN = 0x%08x, LENGTH = 0x%08x\n" $(FP_CONFIG_BASE) $(FP_CONFIG_SIZE) >> $@
101 |
102 | gen/patch.elf: patch.ld gen/nexmon.ld gen/flashpatches.ld gen/memory.ld $(OBJS)
103 | @printf "\033[0;31m LINKING OBJECTS\033[0m => %s (details: log/linker.log, log/linker.err)\n" $@
104 | $(Q)$(CC)ld -T $< -o $@ --gc-sections --print-gc-sections -M >>log/linker.log 2>>log/linker.err
105 |
106 | fw_bcmdhd.bin: init gen/patch.elf $(FW_PATH)/$(RAM_FILE) gen/nexmon.mk gen/flashpatches.mk
107 | $(Q)cp $(FW_PATH)/$(RAM_FILE) $@
108 | @printf "\033[0;31m APPLYING FLASHPATCHES\033[0m gen/flashpatches.mk => %s (details: log/flashpatches.log)\n" $@
109 | $(Q)make -f gen/flashpatches.mk >>log/flashpatches.log 2>>log/flashpatches.log
110 | @printf "\033[0;31m APPLYING PATCHES\033[0m gen/nexmon.mk => %s (details: log/patches.log)\n" $@
111 | $(Q)make -f gen/nexmon.mk >>log/patches.log 2>>log/flashpatches.log
112 |
113 | ###################################################################
114 | # ucode compression related
115 | ###################################################################
116 |
117 | ifneq ($(wildcard src/ucode.asm), )
118 | gen/ucode.bin: src/ucode.asm
119 | @printf "\033[0;31m ASSEMBLING UCODE\033[0m %s => %s\n" $< $@
120 |
121 | ifneq ($(wildcard $(NEXMON_ROOT)/buildtools/b43/assembler/b43-asm.bin), )
122 | $(Q)PATH=$(PATH):$(NEXMON_ROOT)/buildtools/b43/assembler $(NEXMON_ROOT)/buildtools/b43/assembler/b43-asm $< $@ --format raw-le32
123 | else
124 | $(error Warning: please compile b43-asm.bin first)
125 | endif
126 |
127 | else
128 | gen/ucode.bin: $(FW_PATH)/ucode.bin
129 | @printf "\033[0;31m COPYING UCODE\033[0m %s => %s\n" $< $@
130 | $(Q)cp $< $@
131 | endif
132 |
133 | gen/ucode_compressed.bin: gen/ucode.bin
134 | @printf "\033[0;31m COMPRESSING UCODE\033[0m %s => %s\n" $< $@
135 | $(Q)cat $< | $(ZLIBFLATE) > $@
136 |
137 | src/ucode_compressed.c: gen/ucode_compressed.bin
138 | @printf "\033[0;31m GENERATING C FILE\033[0m %s => %s\n" $< $@
139 | $(Q)printf "#pragma NEXMON targetregion \"ucode\"\n\n" > $@
140 | $(Q)cd $(dir $<) && xxd -i $(notdir $<) >> $(shell pwd)/$@
141 |
142 | src/templateram.c: $(FW_PATH)/templateram.bin
143 | @printf "\033[0;31m GENERATING C FILE\033[0m %s => %s\n" $< $@
144 | $(Q)printf "#pragma NEXMON targetregion \"ucode\"\n\n" > $@
145 | $(Q)cd $(dir $<) && xxd -i $(notdir $<) >> $(shell pwd)/$@
146 |
147 | ###################################################################
148 |
149 | check-nexmon-setup-env:
150 | ifndef NEXMON_SETUP_ENV
151 | $(error run 'source setup_env.sh' first in the repository\'s root directory)
152 | endif
153 |
154 | install-firmware: fw_bcmdhd.bin
155 | @printf "\033[0;31m REMOUNTING /system\033[0m\n"
156 | $(Q)adb shell 'su -c "mount -o rw,remount /system"'
157 | @printf "\033[0;31m COPYING TO PHONE\033[0m %s => /sdcard/%s\n" $< $<
158 | $(Q)adb push $< /sdcard/ >> log/adb.log 2>> log/adb.log
159 | @printf "\033[0;31m COPYING\033[0m /sdcard/fw_bcmdhd.bin => /vendor/firmware/fw_bcmdhd.bin\n"
160 | $(Q)adb shell 'su -c "cp /sdcard/fw_bcmdhd.bin /vendor/firmware/fw_bcmdhd.bin"'
161 | @printf "\033[0;31m RELOADING FIRMWARE\033[0m\n"
162 | $(Q)adb shell 'su -c "ifconfig wlan0 down && ifconfig wlan0 up"'
163 |
164 | backup-firmware: FORCE
165 | adb shell 'su -c "cp /vendor/firmware/fw_bcmdhd.bin /sdcard/fw_bcmdhd.orig.bin"'
166 | adb pull /sdcard/fw_bcmdhd.orig.bin
167 |
168 | install-backup: fw_bcmdhd.orig.bin
169 | adb shell 'su -c "mount -o rw,remount /system"' && \
170 | adb push $< /sdcard/ && \
171 | adb shell 'su -c "cp /sdcard/fw_bcmdhd.bin /vendor/firmware/fw_bcmdhd.bin"'
172 | adb shell 'su -c "ifconfig wlan0 down && ifconfig wlan0 up"'
173 |
174 | clean-firmware: FORCE
175 | @printf "\033[0;31m CLEANING\033[0m\n"
176 | $(Q)rm -fr fw_bcmdhd.bin obj gen log src/ucode_compressed.c src/templateram.c
177 |
178 | clean: clean-firmware
179 | $(Q)rm -f BUILD_NUMBER
180 |
181 | FORCE:
182 |
--------------------------------------------------------------------------------
/src/debugger.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | * *
3 | * ########### ########### ########## ########## *
4 | * ############ ############ ############ ############ *
5 | * ## ## ## ## ## ## ## *
6 | * ## ## ## ## ## ## ## *
7 | * ########### #### ###### ## ## ## ## ###### *
8 | * ########### #### # ## ## ## ## # # *
9 | * ## ## ###### ## ## ## ## # # *
10 | * ## ## # ## ## ## ## # # *
11 | * ############ ##### ###### ## ## ## ##### ###### *
12 | * ########### ########### ## ## ## ########## *
13 | * *
14 | * S E C U R E M O B I L E N E T W O R K I N G *
15 | * *
16 | * Warning: *
17 | * *
18 | * Our software may damage your hardware and may void your hardware’s *
19 | * warranty! You use our tools at your own risk and responsibility! *
20 | * *
21 | * License: *
22 | * Copyright (c) 2017 NexMon Team *
23 | * *
24 | * Permission is hereby granted, free of charge, to any person obtaining *
25 | * a copy of this software and associated documentation files (the *
26 | * "Software"), to deal in the Software without restriction, including *
27 | * without limitation the rights to use, copy, modify, merge, publish, *
28 | * distribute copies of the Software, and to permit persons to whom the *
29 | * Software is furnished to do so, subject to the following conditions: *
30 | * *
31 | * The above copyright notice and this permission notice shall be included *
32 | * in all copies or substantial portions of the Software. *
33 | * *
34 | * Any use of the Software which results in an academic publication or *
35 | * other publication which includes a bibliography must include a citation *
36 | * to the author's publication "M. Schulz, D. Wegemer and M. Hollick. *
37 | * NexMon: A Cookbook for Firmware Modifications on Smartphones to Enable *
38 | * Monitor Mode.". *
39 | * *
40 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
41 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
42 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
43 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
44 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
45 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
46 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
47 | * * *
48 | **************************************************************************/
49 |
50 | #pragma NEXMON targetregion "patch"
51 |
52 | #include // definition of firmware version macros
53 | #include // wrapper definitions for functions that already exist in the firmware
54 | #include // structures that are used by the code in the firmware
55 | #include // useful helper functions
56 | #include // macros used to craete patches such as BLPatch, BPatch, ...
57 | #include // contains macros to access the debug hardware
58 |
59 | /**
60 | * Replaces the SP and LR registers on the stack with those of the system mode.
61 | * As we decided to stay in abort mode to handle breakpoints and watchpoints, we need to
62 | * change to system mode to fetch the correct sp and lr registers to store the correct state
63 | * on the stack. The required state is the one before the prefetch/data abort exception.
64 | */
65 | // function implemented in debugger_base.c
66 | extern struct trace * fix_sp_lr(struct trace *trace);
67 | extern void set_abort_stack_pointer(void);
68 |
69 | /**
70 | * Saves one-hot encoded which breakpoint was hit
71 | */
72 | unsigned char breakpoint_hit = 0;
73 |
74 | /**
75 | * Saves one-hot encoded whether we should perform single stepping
76 | */
77 | unsigned char single_stepping = 0;
78 |
79 | /**
80 | * Breakpoint step counter, saves how many steps we performed after triggering the breakpoint
81 | */
82 |
83 | unsigned int breakpoint_cnt0 = 0;
84 | unsigned int breakpoint_cnt1 = 0;
85 | unsigned int breakpoint_cnt2 = 0;
86 | unsigned int breakpoint_cnt3 = 0;
87 |
88 | /**
89 | * Saves one-hot encoded which watchpoint was hit
90 | */
91 | unsigned char watchpoint_hit = 0;
92 |
93 | /**
94 | * Watchpoint hit counter, saves how often a watchpoint was hit
95 | */
96 | unsigned char watchpoint_hit_counter = 0;
97 |
98 | /**
99 | * Watchpoint hit limit, defines how often a watchpoint should trigger
100 | */
101 | unsigned char watchpoint_hit_limit = 20;
102 |
103 | /**
104 | * Watchpoint handler function
105 | */
106 | void __attribute__((optimize("O0")))
107 | handle_data_abort_exception(struct trace *trace)
108 | {
109 | fix_sp_lr(trace);
110 |
111 | // TODO
112 | // Currently I do not know how to find out, which watchpoint was triggered, so here I always handle watchpoint 0
113 | watchpoint_hit |= DBGWP0;
114 |
115 | // Disable the watchpoint so that the instruction that triggered the watchpoint can be executed without triggering the watchpoint again.
116 | dbg_disable_watchpoint(0);
117 | dbg_disable_watchpoint(1);
118 | dbg_disable_watchpoint(2);
119 | dbg_disable_watchpoint(3);
120 |
121 | printf(" WP hit pc=%08x\n", trace->pc);
122 |
123 | // Set breakpoint 3 to reset the watchpoint after executing the instruction that triggered the watchpoint.
124 | dbg_set_breakpoint_for_addr_mismatch(3, trace->PC);
125 | }
126 |
127 | /**
128 | * Breakpoint handler function
129 | */
130 | void __attribute__((optimize("O0")))
131 | handle_pref_abort_exception(struct trace *trace)
132 | {
133 | fix_sp_lr(trace);
134 |
135 | // check whether breakpoint 0 is enabled
136 | if(dbg_is_breakpoint_enabled(0)) {
137 | if (dbg_triggers_on_breakpoint_address(0, trace->pc)) {
138 | // to continue executed on the instruction where breakpoint 0 triggered, we set the breakpoint type
139 | // to address mismatch to trigger on any instruction except the breakpoint address
140 | dbg_set_breakpoint_type_to_instr_addr_mismatch(0);
141 |
142 | if (!strncmp((char *) trace->r1, "sdpcmd_dpc", 10)) {
143 | printf(" BP0 step %d: pc=%08x *r1=%s\n", breakpoint_cnt0, trace->pc, trace->r1);
144 | // activate single-stepping for this breakpoint
145 | single_stepping |= DBGBP0;
146 | }
147 |
148 | // to know which breakpoint mismatch was triggerd on a next breakpoint hit, we set a bit in the breakpoint_hit variable
149 | breakpoint_hit |= DBGBP0;
150 | } else if (breakpoint_hit & DBGBP0) {
151 | // check whether single-stepping should be activated for this breakpoint
152 | if (single_stepping & DBGBP0) {
153 | // we reset the breakpoint for address mismatch for single-stepping
154 | dbg_set_breakpoint_for_addr_mismatch(0, trace->pc);
155 |
156 | // increase the breakpoint step counter
157 | breakpoint_cnt0++;
158 |
159 | printf(" BP0 step %d: pc=%08x\n", breakpoint_cnt0, trace->pc);
160 |
161 | // after 4 steps, we want to stop single-stepping
162 | if ((breakpoint_cnt0 == 4)) {
163 | // we can now reset the breakpoint to trigger on printf again (in case we do not want to disable it)
164 | dbg_set_breakpoint_for_addr_match(0, 0x126f0);
165 |
166 | // we reset the breakpoint counter back to zero
167 | breakpoint_cnt0 = 0;
168 |
169 | // we disable the breakpoint
170 | //dbg_disable_breakpoint(0);
171 |
172 | // we unset the bit in the breakpoint_hit variable for breakpoint 0
173 | breakpoint_hit &= ~DBGBP0;
174 |
175 | // we disable single-stepping for this breakpoint
176 | single_stepping &= ~DBGBP0;
177 |
178 | printf(" BP0 single-stepping done\n");
179 | }
180 | } else {
181 | // we reset the breakpoint for address matching
182 | dbg_set_breakpoint_type_to_instr_addr_match(0);
183 |
184 | // we reset the breakpoint counter back to zero
185 | breakpoint_cnt0 = 0;
186 |
187 | // we unset the bit in the breakpoint_hit variable for breakpoint 0
188 | breakpoint_hit &= ~DBGBP0;
189 | }
190 | }
191 | }
192 |
193 | // check whether breakpoint 3 is enabled
194 | if (dbg_is_breakpoint_enabled(3)) {
195 | // Used to reset watchpoint
196 | if (watchpoint_hit & DBGWP0) {
197 | dbg_disable_breakpoint(3);
198 |
199 | // we unset the bit in the watchpoint_hit variable for watchpoint 0
200 | watchpoint_hit &= ~DBGWP0;
201 |
202 | // reenable watchpoint 0 only if the hit counter is below our limit
203 | if (++watchpoint_hit_counter < watchpoint_hit_limit) {
204 | dbg_enable_watchpoint(0);
205 | } else {
206 | printf("WP0 not reset (%d)\n", watchpoint_hit_counter);
207 | }
208 | }
209 | }
210 | }
211 |
212 | void
213 | set_debug_registers(void)
214 | {
215 | set_abort_stack_pointer();
216 | dbg_unlock_debug_registers();
217 | dbg_disable_breakpoint(0);
218 | dbg_disable_breakpoint(1);
219 | dbg_disable_breakpoint(2);
220 | dbg_disable_breakpoint(3);
221 | dbg_enable_monitor_mode_debugging();
222 |
223 | // Programm Breakpoint to match the instruction we want to hit
224 | dbg_set_breakpoint_for_addr_match(0, 0x126f0); // trigger on printf
225 |
226 | // Program watchpoint to match the address we want to monitor
227 | //dbg_set_watchpoint_for_addr_match(0, 0x1D3A59); // trigger on "TCAM: %d used: %d exceed:%d" string
228 | dbg_set_watchpoint_for_addr_match(0, 0x1FC2A4); // trigger on "%s: Broadcom SDPCMD CDC driver" string
229 | }
230 |
--------------------------------------------------------------------------------
/src/debugger_base.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | * *
3 | * ########### ########### ########## ########## *
4 | * ############ ############ ############ ############ *
5 | * ## ## ## ## ## ## ## *
6 | * ## ## ## ## ## ## ## *
7 | * ########### #### ###### ## ## ## ## ###### *
8 | * ########### #### # ## ## ## ## # # *
9 | * ## ## ###### ## ## ## ## # # *
10 | * ## ## # ## ## ## ## # # *
11 | * ############ ##### ###### ## ## ## ##### ###### *
12 | * ########### ########### ## ## ## ########## *
13 | * *
14 | * S E C U R E M O B I L E N E T W O R K I N G *
15 | * *
16 | * Warning: *
17 | * *
18 | * Our software may damage your hardware and may void your hardware’s *
19 | * warranty! You use our tools at your own risk and responsibility! *
20 | * *
21 | * License: *
22 | * Copyright (c) 2017 NexMon Team *
23 | * *
24 | * Permission is hereby granted, free of charge, to any person obtaining *
25 | * a copy of this software and associated documentation files (the *
26 | * "Software"), to deal in the Software without restriction, including *
27 | * without limitation the rights to use, copy, modify, merge, publish, *
28 | * distribute copies of the Software, and to permit persons to whom the *
29 | * Software is furnished to do so, subject to the following conditions: *
30 | * *
31 | * The above copyright notice and this permission notice shall be included *
32 | * in all copies or substantial portions of the Software. *
33 | * *
34 | * Any use of the Software which results in an academic publication or *
35 | * other publication which includes a bibliography must include a citation *
36 | * to the author's publication "M. Schulz, D. Wegemer and M. Hollick. *
37 | * NexMon: A Cookbook for Firmware Modifications on Smartphones to Enable *
38 | * Monitor Mode.". *
39 | * *
40 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
41 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
42 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
43 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
44 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
45 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
46 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
47 | * * *
48 | **************************************************************************/
49 |
50 | #pragma NEXMON targetregion "patch"
51 |
52 | #include // definition of firmware version macros
53 | #include // wrapper definitions for functions that already exist in the firmware
54 | #include // structures that are used by the code in the firmware
55 | #include // useful helper functions
56 | #include // macros used to craete patches such as BLPatch, BPatch, ...
57 | #include // contains macros to access the debug hardware
58 |
59 | // functions implemented in debugger.c
60 | extern void handle_pref_abort_exception(struct trace *trace);
61 | extern void set_debug_registers(void);
62 |
63 | /**
64 | * Replaces the SP and LR registers on the stack with those of the system mode.
65 | * As we decided to stay in abort mode to handle breakpoints and watchpoints, we need to
66 | * change to system mode to fetch the correct sp and lr registers to store the correct state
67 | * on the stack. The required state is the one before the prefetch/data abort exception.
68 | */
69 | struct trace * __attribute__((optimize("O0")))
70 | fix_sp_lr(struct trace *trace)
71 | {
72 | register unsigned int sp_sys asm("r1");
73 | register unsigned int lr_sys asm("r2");
74 |
75 | dbg_disable_monitor_mode_debugging();
76 | dbg_change_processor_mode(DBG_PROCESSOR_MODE_SYS);
77 | asm("mov %[result], sp" : [result] "=r" (sp_sys));
78 | asm("mov %[result], lr" : [result] "=r" (lr_sys));
79 | dbg_change_processor_mode(DBG_PROCESSOR_MODE_ABT);
80 | dbg_enable_monitor_mode_debugging();
81 |
82 | trace->lr = lr_sys;
83 | trace->sp = sp_sys;
84 |
85 | return trace;
86 | }
87 |
88 | // 1 KiBi for stack in abort mode
89 | uint32 stack_abt[256] = { 0x54424153 };
90 |
91 | /**
92 | * Sets the stack pointer of the abort mode to be at the end of the current stack area, a part that is likely not used during regular program execution
93 | */
94 | void __attribute__((optimize("O0")))
95 | set_abort_stack_pointer(void)
96 | {
97 | register unsigned int sp_abt asm("r0") = (uint32) &stack_abt[255];
98 |
99 | dbg_change_processor_mode(DBG_PROCESSOR_MODE_ABT);
100 | asm("mov sp, %[value]" : : [value] "r" (sp_abt));
101 | dbg_change_processor_mode(DBG_PROCESSOR_MODE_SYS);
102 | }
103 |
104 | /**
105 | * is called before the wlc_ucode_download function to print our hello world message
106 | */
107 | __attribute__((at(0x180020, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
108 | __attribute__((naked)) void
109 | c_main_hook(void)
110 | {
111 | asm(
112 | "push {r0-r3,lr}\n" // Push the registers that could be modified by a call to a C function
113 | "bl set_debug_registers\n" // Call a C function
114 | "pop {r0-r3,lr}\n" // Pop the registers that were saved before
115 | "b c_main\n" // Call the hooked function
116 | );
117 | }
118 |
119 | __attribute__((at(0x181240, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
120 | GenericPatch4(c_main_hook, c_main_hook + 1);
121 |
122 | /**
123 | * Exception handler that is triggered on reset/startup/powerup
124 | */
125 | __attribute__((naked)) void
126 | tr_reset_hook(void)
127 | {
128 | asm(
129 | "mrs r0, cpsr\n"
130 | "mov r1, #0x1f\n"
131 | "bic r0, r0, r1\n"
132 | "mov r1, #0xdf\n"
133 | "orr r0, r0, r1\n"
134 | "msr cpsr_fc, r0\n"
135 | "b setup\n"
136 | );
137 | }
138 |
139 | /**
140 | * Exception handler that is triggered by watchpoint or illegal address access
141 | */
142 | __attribute__((at(0x180FAA, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
143 | __attribute__((naked)) void
144 | tr_data_abort_hook(void)
145 | {
146 | asm(
147 | "sub lr, lr, #8\n" // we directly subtract 4 from the link register (original code overwrites the stack pointer first)
148 | "srsdb sp!, #0x17\n" // stores return state (LR and SPSR) to the stack of the abort mode (0x17) (original codes switches to system mode (0x1F))
149 | "push {r0}\n"
150 | "push {lr}\n" // here we do not get the expected link register from the system mode, but the link register from the abort mode
151 | "sub sp, sp, #24\n"
152 | "push {r0-r7}\n"
153 | "eor r0, r0, r0\n"
154 | "add r0, r0, #4\n"
155 | "b handle_exceptions\n"
156 | );
157 | }
158 |
159 | /**
160 | * Exception handler that is triggered by breakpoint
161 | */
162 | __attribute__((at(0x180F88, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
163 | __attribute__((naked)) void
164 | tr_pref_abort_hook(void)
165 | {
166 | asm(
167 | "sub lr, lr, #4\n" // we directly subtract 4 from the link register (original code overwrites the stack pointer first)
168 | "srsdb sp!, #0x17\n" // stores return state (LR and SPSR) to the stack of the abort mode (0x17) (original codes switches to system mode (0x1F))
169 | "push {r0}\n"
170 | "push {lr}\n" // here we do not get the expected link register from the system mode, but the link register from the abort mode
171 | "sub sp, sp, #24\n"
172 | "push {r0-r7}\n"
173 | "eor r0, r0, r0\n"
174 | "add r0, r0, #3\n"
175 | "b handle_exceptions\n"
176 | );
177 | }
178 |
179 | __attribute__((naked)) void
180 | choose_exception_handler(void)
181 | {
182 | asm(
183 | "cmp r0, #3\n"
184 | "beq label_pref_abort\n"
185 | "cmp r0, #4\n"
186 | "beq label_data_abort\n"
187 | "label_continue_exception:\n"
188 | "cmp r0, #6\n" // check if fast interrupt
189 | "bne label_other_exception\n" // if interrupt was not a fast interrupt
190 | "cmp r1, #64\n" // if FIQ was enabled, enable it again
191 | "beq label_other_exception\n"
192 | "cpsie f\n"
193 | "label_other_exception:\n"
194 | "mov r0, sp\n"
195 | "push {lr}\n"
196 | "pop {lr}\n"
197 | "b dump_stack_print_dbg_stuff_intr_handler\n"
198 | "label_pref_abort:\n"
199 | "mov r0, sp\n"
200 | "push {lr}\n"
201 | "pop {lr}\n"
202 | "b handle_pref_abort_exception\n"
203 | "label_data_abort:\n"
204 | "mrc p15, 0, r0, c5, c0, 0\n" // read DFSR
205 | "and r0, r0, #0x1F\n" // select FS bits from DFSR
206 | "cmp r0, #2\n" // compare FS to "debug event"
207 | "bne label_continue_exception\n" // if data abort not caused by a "debug event", go to regular exception handler
208 | "mov r0, sp\n"
209 | "b handle_data_abort_exception\n"
210 | );
211 | }
212 |
213 | /**
214 | *
215 | */
216 | __attribute__((at(0x181032, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
217 | __attribute__((naked)) void
218 | handle_exceptions(void)
219 | {
220 | asm(
221 | "mov r4, sp\n"
222 | "add r4, r4, #64\n"
223 | "ldmia r4!, {r1,r3}\n"
224 | "mrs r2, cpsr\n"
225 | "push {r0-r3}\n"
226 | "sub r4, r4, #12\n"
227 | "str r1, [r4]\n"
228 | "and r1, r3, #64\n" // r3 is CPSR_SYS, bit 6 is the FIQ mask bit
229 | "mov r7, sp\n"
230 | "add r7, r7, #88\n"
231 | "mov r6, r12\n"
232 | "mov r5, r11\n"
233 | "mov r4, r10\n"
234 | "mov r3, r9\n"
235 | "mov r2, r8\n"
236 | "add sp, sp, #72\n"
237 | "push {r2-r7}\n"
238 | /*
239 | * Now the stack looks like this:
240 | * SPSR -> CPSR_SYS
241 | * LR_ABT -> PC_SYS
242 | * PC_SYS
243 | * LR_ABT call fix_sp_lr to change this to LR_SYS
244 | * SP_ABT call fix_sp_lr to change this to SP_SYS
245 | * R12
246 | * R11
247 | * R10
248 | * R9
249 | * R8
250 | * R7
251 | * R6
252 | * R5
253 | * R4
254 | * R3
255 | * R2
256 | * R1
257 | * R0
258 | * CPSR_SYS
259 | * CPSR_ABT
260 | * PC_SYS
261 | * Exception ID
262 | */
263 | "sub sp, sp, #48\n"
264 | "bl choose_exception_handler\n"
265 | "cpsid if\n"
266 | "add sp, sp, #48\n"
267 | "pop {r0-r6}\n"
268 | "mov r8, r0\n"
269 | "mov r9, r1\n"
270 | "mov r10, r2\n"
271 | "mov r11, r3\n"
272 | "mov r12, r4\n"
273 | "mov lr, r6\n"
274 | "sub sp, sp, #60\n"
275 | "pop {r0-r7}\n"
276 | "add sp, sp, #32\n"
277 | "rfefd sp!\n"
278 | );
279 | }
280 |
281 | // The following patch, that is necessary to access debug registers in an interrupt handler breaks normal wifi operation
282 | // write nops over the si_update_chipcontrol_shm(sii, 5, 16, 0) call in si_setup_cores
283 | __attribute__((at(0x18545A, "", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704)))
284 | GenericPatch4(activate_debugger, 0xBF00BF00);
285 |
286 |
287 |
--------------------------------------------------------------------------------