summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/hwstub/hwstub_protocol.h (renamed from utils/hwstub/hwemul_protocol.h)68
-rw-r--r--utils/hwstub/lib/Makefile17
-rw-r--r--utils/hwstub/lib/hwemul_protocol.h1
-rw-r--r--utils/hwstub/lib/hwstub.c (renamed from utils/hwstub/lib/hwemul.c)41
-rw-r--r--utils/hwstub/lib/hwstub.h (renamed from utils/hwstub/lib/hwemul.h)39
-rw-r--r--utils/hwstub/lib/hwstub_protocol.h1
-rw-r--r--utils/hwstub/stmp/Makefile87
-rw-r--r--utils/hwstub/stmp/config.h29
-rw-r--r--utils/hwstub/stmp/format.h6
-rw-r--r--utils/hwstub/stmp/hwstub.db (renamed from utils/hwstub/stmp/hwemul.db)6
-rw-r--r--utils/hwstub/stmp/hwstub.lds (renamed from utils/hwstub/stmp/hwemul.lds)1
-rw-r--r--utils/hwstub/stmp/link.lds49
-rw-r--r--utils/hwstub/stmp/logf.h6
-rw-r--r--utils/hwstub/stmp/main.c536
-rw-r--r--utils/hwstub/stmp/memcpy.S176
-rw-r--r--utils/hwstub/stmp/memmove.S190
-rw-r--r--utils/hwstub/stmp/memset.S98
-rw-r--r--utils/hwstub/stmp/protocol.h2
-rw-r--r--utils/hwstub/stmp/stddef.h6
-rw-r--r--utils/hwstub/stmp/string.h6
-rw-r--r--utils/hwstub/stmp/system.h6
-rw-r--r--utils/hwstub/tools/Makefile36
-rw-r--r--utils/hwstub/tools/hwemul_tool.c558
-rw-r--r--utils/hwstub/tools/hwstub_load.cpp316
-rw-r--r--utils/hwstub/tools/hwstub_shell.cpp873
-rw-r--r--utils/hwstub/tools/init.lua104
26 files changed, 2063 insertions, 1195 deletions
diff --git a/utils/hwstub/hwemul_protocol.h b/utils/hwstub/hwstub_protocol.h
index f11fd91352..41be3957e8 100644
--- a/utils/hwstub/hwemul_protocol.h
+++ b/utils/hwstub/hwstub_protocol.h
@@ -18,19 +18,19 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_PROTOCOL__
-#define __HWEMUL_PROTOCOL__
+#ifndef __HWSTUB_PROTOCOL__
+#define __HWSTUB_PROTOCOL__
-#define HWEMUL_CLASS 0xfe
-#define HWEMUL_SUBCLASS 0xac
-#define HWEMUL_PROTOCOL 0x1d
+#define HWSTUB_CLASS 0xfe
+#define HWSTUB_SUBCLASS 0xac
+#define HWSTUB_PROTOCOL 0x1d
-#define HWEMUL_VERSION_MAJOR 2
-#define HWEMUL_VERSION_MINOR 8
-#define HWEMUL_VERSION_REV 2
+#define HWSTUB_VERSION_MAJOR 2
+#define HWSTUB_VERSION_MINOR 9
+#define HWSTUB_VERSION_REV 2
-#define HWEMUL_USB_VID 0xfee1
-#define HWEMUL_USB_PID 0xdead
+#define HWSTUB_USB_VID 0xfee1
+#define HWSTUB_USB_PID 0xdead
/**
* Control commands
@@ -41,22 +41,22 @@
*/
/* list of commands */
-#define HWEMUL_GET_INFO 0 /* mandatory */
-#define HWEMUL_GET_LOG 1 /* optional */
-#define HWEMUL_RW_MEM 2 /* optional */
-#define HWEMUL_CALL 3 /* optional */
-#define HWEMUL_JUMP 4 /* optional */
-#define HWEMUL_AES_OTP 5 /* optional */
+#define HWSTUB_GET_INFO 0 /* mandatory */
+#define HWSTUB_GET_LOG 1 /* optional */
+#define HWSTUB_RW_MEM 2 /* optional */
+#define HWSTUB_CALL 3 /* optional */
+#define HWSTUB_JUMP 4 /* optional */
+#define HWSTUB_AES_OTP 5 /* optional */
/**
- * HWEMUL_GET_INFO: get some information about an aspect of the device.
+ * HWSTUB_GET_INFO: get some information about an aspect of the device.
* The wIndex field of the SETUP specifies which information to get. */
/* list of possible information */
-#define HWEMUL_INFO_VERSION 0
-#define HWEMUL_INFO_LAYOUT 1
-#define HWEMUL_INFO_STMP 2
-#define HWEMUL_INFO_FEATURES 3
+#define HWSTUB_INFO_VERSION 0
+#define HWSTUB_INFO_LAYOUT 1
+#define HWSTUB_INFO_STMP 2
+#define HWSTUB_INFO_FEATURES 3
struct usb_resp_info_version_t
{
@@ -86,11 +86,11 @@ struct usb_resp_info_stmp_t
} __attribute__((packed));
/* list of possible features */
-#define HWEMUL_FEATURE_LOG (1 << 0)
-#define HWEMUL_FEATURE_MEM (1 << 1)
-#define HWEMUL_FEATURE_CALL (1 << 2)
-#define HWEMUL_FEATURE_JUMP (1 << 2)
-#define HWEMUL_FEATURE_AES_OTP (1 << 3)
+#define HWSTUB_FEATURE_LOG (1 << 0)
+#define HWSTUB_FEATURE_MEM (1 << 1)
+#define HWSTUB_FEATURE_CALL (1 << 2)
+#define HWSTUB_FEATURE_JUMP (1 << 2)
+#define HWSTUB_FEATURE_AES_OTP (1 << 3)
struct usb_resp_info_features_t
{
@@ -98,30 +98,32 @@ struct usb_resp_info_features_t
};
/**
- * HWEMUL_GET_LOG: only if has HWEMUL_FEATURE_LOG.
+ * HWSTUB_GET_LOG: only if has HWSTUB_FEATURE_LOG.
* The log is returned as part of the control transfer.
*/
/**
- * HWEMUL_RW_MEM: only if has HWEMUL_FEATURE_MEM.
+ * HWSTUB_RW_MEM: only if has HWSTUB_FEATURE_MEM.
* The 32-bit address is split into two parts.
* The low 16-bit are stored in wValue and the upper
* 16-bit are stored in wIndex. Depending on the transfer direction,
- * the transfer is either a read or a write. */
+ * the transfer is either a read or a write.
+ * The read/write on the device are guaranteed to be 16-bit/32-bit when
+ * possible, making it suitable to read/write registers. */
/**
- * HWEMUL_x: only if has HWEMUL_FEATURE_x where x=CALL or JUMP.
+ * HWSTUB_x: only if has HWSTUB_FEATURE_x where x=CALL or JUMP.
* The 32-bit address is split into two parts.
* The low 16-bit are stored in wValue and the upper
* 16-bit are stored in wIndex. Depending on the transfer direction,
* the transfer is either a read or a write. */
/**
- * HWEMUL_AES_OTP: only if has HWEMUL_FEATURE_AES_OTP.
+ * HWSTUB_AES_OTP: only if has HWSTUB_FEATURE_AES_OTP.
* The control transfer contains the data to be en/decrypted and the data
* is sent back on the interrupt endpoint. The first 16-bytes of the data
* are interpreted as the IV. The output format is the same.
* The wValue field contains the parameters of the process. */
-#define HWEMUL_AES_OTP_ENCRYPT (1 << 0)
+#define HWSTUB_AES_OTP_ENCRYPT (1 << 0)
-#endif /* __HWEMUL_PROTOCOL__ */
+#endif /* __HWSTUB_PROTOCOL__ */
diff --git a/utils/hwstub/lib/Makefile b/utils/hwstub/lib/Makefile
index 7280fe8e38..7c455e4586 100644
--- a/utils/hwstub/lib/Makefile
+++ b/utils/hwstub/lib/Makefile
@@ -2,26 +2,19 @@ CC=gcc
AR=ar
CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC
LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC
-LIB=libhwemul.a
-REGTOOLS=../../regtools
-DESC=$(REGTOOLS)/desc
-HWEMULGEN=$(REGTOOLS)/hwemulgen
-HWEMULSOC_PREFIX=hwemul_soc
-SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c
+LIB=libhwstub.a
+SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
-all: $(LIB) $(EXEC)
+all: $(LIB)
-$(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h:
- $(HWEMULGEN) $(DESC)/*.xml $(HWEMULSOC_PREFIX)
-
-%.o: %.c $(HWEMULSOC_PREFIX).h
+%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(LIB): $(OBJ)
$(AR) rcs $@ $^
clean:
- rm -rf $(OBJ) $(LIB) $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h
+ rm -rf $(OBJ) $(LIB)
diff --git a/utils/hwstub/lib/hwemul_protocol.h b/utils/hwstub/lib/hwemul_protocol.h
deleted file mode 100644
index d3ffb6ce00..0000000000
--- a/utils/hwstub/lib/hwemul_protocol.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../hwemul_protocol.h"
diff --git a/utils/hwstub/lib/hwemul.c b/utils/hwstub/lib/hwstub.c
index 3e2e6de38a..92010e710b 100644
--- a/utils/hwstub/lib/hwemul.c
+++ b/utils/hwstub/lib/hwstub.c
@@ -18,15 +18,14 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include "hwemul.h"
-#include "hwemul_soc.h"
+#include "hwstub.h"
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/* requires then ->handle field only */
-int hwemul_probe(struct hwemul_device_t *dev)
+int hwstub_probe(struct hwstub_device_t *dev)
{
libusb_device *mydev = libusb_get_device(dev->handle);
@@ -44,9 +43,9 @@ int hwemul_probe(struct hwemul_device_t *dev)
const struct libusb_interface_descriptor *interface =
&config->interface[intf].altsetting[0];
if(interface->bNumEndpoints != 3 ||
- interface->bInterfaceClass != HWEMUL_CLASS ||
- interface->bInterfaceSubClass != HWEMUL_SUBCLASS ||
- interface->bInterfaceProtocol != HWEMUL_PROTOCOL)
+ interface->bInterfaceClass != HWSTUB_CLASS ||
+ interface->bInterfaceSubClass != HWSTUB_SUBCLASS ||
+ interface->bInterfaceProtocol != HWSTUB_PROTOCOL)
continue;
dev->intf = intf;
dev->bulk_in = dev->bulk_out = dev->int_in = -1;
@@ -73,26 +72,26 @@ int hwemul_probe(struct hwemul_device_t *dev)
return libusb_claim_interface(dev->handle, intf);
}
-int hwemul_release(struct hwemul_device_t *dev)
+int hwstub_release(struct hwstub_device_t *dev)
{
return libusb_release_interface(dev->handle, dev->intf);
}
-int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz)
+int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
- HWEMUL_GET_INFO, 0, idx, info, sz, 1000);
+ HWSTUB_GET_INFO, 0, idx, info, sz, 1000);
}
-int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz)
+int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
- HWEMUL_GET_LOG, 0, 0, buf, sz, 1000);
+ HWSTUB_GET_LOG, 0, 0, buf, sz, 1000);
}
-int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
+int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
{
size_t tot_sz = 0;
while(sz)
@@ -101,7 +100,7 @@ int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *bu
int ret = libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
(read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
- HWEMUL_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
+ HWSTUB_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
if(ret != xfer)
return ret;
sz -= xfer;
@@ -112,23 +111,23 @@ int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *bu
return tot_sz;
}
-int hwemul_call(struct hwemul_device_t *dev, uint32_t addr)
+int hwstub_call(struct hwstub_device_t *dev, uint32_t addr)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
- LIBUSB_ENDPOINT_OUT, HWEMUL_CALL, addr & 0xffff, addr >> 16, NULL, 0,
+ LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0,
1000);
}
-int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr)
+int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
- LIBUSB_ENDPOINT_OUT, HWEMUL_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
+ LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
1000);
}
-const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
+const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp)
{
switch(stmp->chipid)
{
@@ -139,7 +138,7 @@ const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
}
}
-const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
+const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp)
{
switch(stmp->chipid)
{
@@ -159,11 +158,11 @@ const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
}
}
-int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param)
+int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param)
{
int ret = libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
- LIBUSB_ENDPOINT_OUT, HWEMUL_AES_OTP, param, 0, buf, sz,
+ LIBUSB_ENDPOINT_OUT, HWSTUB_AES_OTP, param, 0, buf, sz,
1000);
if(ret <0 || (unsigned)ret != sz)
return -1;
diff --git a/utils/hwstub/lib/hwemul.h b/utils/hwstub/lib/hwstub.h
index 376ba65381..ed058dfa3b 100644
--- a/utils/hwstub/lib/hwemul.h
+++ b/utils/hwstub/lib/hwstub.h
@@ -18,12 +18,15 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL__
-#define __HWEMUL__
+#ifndef __HWSTUB__
+#define __HWSTUB__
#include <libusb.h>
-#include "hwemul_protocol.h"
-#include "hwemul_soc.h"
+#include "hwstub_protocol.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/**
*
@@ -31,7 +34,7 @@
*
*/
-struct hwemul_device_t
+struct hwstub_device_t
{
libusb_device_handle *handle;
int intf;
@@ -41,23 +44,27 @@ struct hwemul_device_t
};
/* Requires then ->handle field only. Returns 0 on success */
-int hwemul_probe(struct hwemul_device_t *dev);
+int hwstub_probe(struct hwstub_device_t *dev);
/* Returns 0 on success */
-int hwemul_release(struct hwemul_device_t *dev);
+int hwstub_release(struct hwstub_device_t *dev);
/* Returns number of bytes filled */
-int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz);
+int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz);
/* Returns number of bytes filled */
-int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz);
+int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
/* Returns number of bytes written/read or <0 on error */
-int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
+int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
/* Returns <0 on error */
-int hwemul_call(struct hwemul_device_t *dev, uint32_t addr);
-int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr);
+int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);
+int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr);
/* Returns <0 on error. The size must be a multiple of 16. */
-int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param);
+int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param);
+
+const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp);
+const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp);
-const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp);
-const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp);
+#ifdef __cplusplus
+} // extern "C"
+#endif
-#endif /* __HWEMUL__ */ \ No newline at end of file
+#endif /* __HWSTUB__ */ \ No newline at end of file
diff --git a/utils/hwstub/lib/hwstub_protocol.h b/utils/hwstub/lib/hwstub_protocol.h
new file mode 100644
index 0000000000..35510fa9b2
--- /dev/null
+++ b/utils/hwstub/lib/hwstub_protocol.h
@@ -0,0 +1 @@
+#include "../hwstub_protocol.h"
diff --git a/utils/hwstub/stmp/Makefile b/utils/hwstub/stmp/Makefile
index ca61fe392d..7fd33c3d9e 100644
--- a/utils/hwstub/stmp/Makefile
+++ b/utils/hwstub/stmp/Makefile
@@ -1,58 +1,51 @@
-PREFIX?=arm-elf-eabi-
-CC=$(PREFIX)gcc
-LD=$(PREFIX)gcc
-AS=$(PREFIX)gcc
-OC=$(PREFIX)objcopy
-SBTOOLS=../../sbtools/
+#
+# common
+#
+CC=arm-elf-eabi-gcc
+LD=arm-elf-eabi-gcc
+AS=arm-elf-eabi-gcc
+OC=arm-elf-eabi-objcopy
CFLAGS=-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -mcpu=arm926ej-s -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init -ffunction-sections
-CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700
ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
-ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__
OCFLAGS=
-LINKER_FILE=hwemul.lds
-LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map
-LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map
+LINKER_FILE=hwstub.lds
+TMP_LDS=link.lds
+TMP_MAP=hwstub.map
+LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP)
SRC_C=$(wildcard *.c)
SRC_S=$(wildcard *.S)
OBJ_C=$(SRC_C:.c=.o)
OBJ_S=$(SRC_S:.S=.o)
-OBJ_C_3700=$(SRC_C:.c=.3700.o)
-OBJ_S_3700=$(SRC_S:.S=.3700.o)
OBJ=$(OBJ_C) $(OBJ_S)
-OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700)
OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
-OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700))
DEPS=$(OBJ:.o=.d)
-EXEC_ELF=hwemul.elf
-EXEC_SB=hwemul.sb
-EXEC_ELF_3700=hwemul3700.elf
-EXEC_SB_3700=hwemul3700.sb
+EXEC_ELF=hwstub.elf
+#
+# image production
+#
+TOOLS=../../../tools
+SBTOOLS=../../imxtools/sbtools
+
+# sb (stmp37xx)
+EXEC_SB=hwstub.sb
ELF2SB=$(SBTOOLS)/elftosb -d
-ELF2SB_CMD=-c hwemul.db
-ELF2SB_KEY=-z
-SBLOADER=$(SBTOOLS)/sbloader
-SBLOADER_CMD=0 $(EXEC_SB)
-SBLOADER_CMD_3700=0 $(EXEC_SB_3700)
+ELF2SB_CMD=-c hwstub.db
+ELF2SB_KEY?=-z
-TOOLS=../../../../tools/
-SCRAMBLE=$(TOOLS)/scramble
+# sb1 (stmp36xx)
+EXEC_SB1=hwstub.sb1
+ELF2SB1_CMD=-loadjump $(EXEC_ELF)
+ELF2SB1_KEY?=
+ELF2SB1=$(SBTOOLS)/elftosb1 -d
-EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700)
+EXEC=$(EXEC_ELF) $(EXEC_SB) $(EXEC_SB1)
all: $(EXEC)
# pull in dependency info for *existing* .o files
-include $(DEPS)
-%.3700.o: %.c
- $(CC) $(CFLAGS_3700) -c -o $@ $<
- $(CC) -MM $(CFLAGS_3700) $*.c > $*.d
- @cp -f $*.d $*.d.tmp
- @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
- sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
- @rm -f $*.d.tmp
-
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(CC) -MM $(CFLAGS) $*.c > $*.d
@@ -61,32 +54,20 @@ all: $(EXEC)
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
@rm -f $*.d.tmp
-%.3700.o: %.S
- $(AS) $(ASFLAGS_3700) -c -o $@ $<
-
%.o: %.S
$(AS) $(ASFLAGS) -c -o $@ $<
-link.lds: $(LINKER_FILE)
+$(TMP_LDS): $(LINKER_FILE)
$(CC) -E -x c - < $< | sed '/#/d' > $@
-
-$(EXEC_ELF): $(OBJ) link.lds
+
+$(EXEC_ELF): $(OBJ) $(TMP_LDS)
$(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
$(EXEC_SB): $(EXEC_ELF)
$(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
-$(EXEC_ELF_3700): $(OBJ_3700) link.lds
- $(LD) $(LDFLAGS_3700) -o $@ $(OBJ_EXCEPT_CRT0_3700)
-
-$(EXEC_SB_3700): $(EXEC_ELF_3700)
- $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
-
-sbload: $(EXEC_SB)
- $(SBLOADER) $(SBLOADER_CMD)
-
-sbload3700: $(EXEC_SB_3700)
- $(SBLOADER) $(SBLOADER_CMD_3700)
+$(EXEC_SB1): $(EXEC_ELF)
+ $(ELF2SB1) $(ELF2SB1_CMD) $(ELF2SB1_KEY) -o $@
clean:
- rm -rf $(OBJ) $(OBJ_3700) $(DEPS) $(EXEC) *.map
+ rm -rf $(OBJ) $(DEPS) $(EXEC) $(TMP_LDS) $(TMP_MAP) \ No newline at end of file
diff --git a/utils/hwstub/stmp/config.h b/utils/hwstub/stmp/config.h
index 6bd995e147..9d6de07f33 100644
--- a/utils/hwstub/stmp/config.h
+++ b/utils/hwstub/stmp/config.h
@@ -18,8 +18,8 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_CONFIG__
-#define __HWEMUL_CONFIG__
+#ifndef __HWSTUB_CONFIG__
+#define __HWSTUB_CONFIG__
#define MEMORYSIZE 0
#define STACK_SIZE 0x1000
@@ -30,4 +30,27 @@
#define DRAM_ORIG 0x40000000
#define DRAM_SIZE (MEMORYSIZE * 0x100000)
-#endif /* __HWEMUL_CONFIG__ */
+#define CPU_ARM
+#define ARM_ARCH 5
+
+#if defined(CPU_ARM) && defined(__ASSEMBLER__)
+/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */
+.macro ldmpc cond="", order="ia", regs
+#if ARM_ARCH == 4 && defined(USE_THUMB)
+ ldm\cond\order sp!, { \regs, lr }
+ bx\cond lr
+#else
+ ldm\cond\order sp!, { \regs, pc }
+#endif
+.endm
+.macro ldrpc cond=""
+#if ARM_ARCH == 4 && defined(USE_THUMB)
+ ldr\cond lr, [sp], #4
+ bx\cond lr
+#else
+ ldr\cond pc, [sp], #4
+#endif
+.endm
+#endif
+
+#endif /* __HWSTUB_CONFIG__ */
diff --git a/utils/hwstub/stmp/format.h b/utils/hwstub/stmp/format.h
index a514c882ba..2ad4229f1e 100644
--- a/utils/hwstub/stmp/format.h
+++ b/utils/hwstub/stmp/format.h
@@ -18,12 +18,12 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_FORMAT__
-#define __HWEMUL_FORMAT__
+#ifndef __HWSTUB_FORMAT__
+#define __HWSTUB_FORMAT__
#include <stdarg.h>
void vuprintf(int (*push)(void *userp, unsigned char data),
void *userp, const char *fmt, va_list ap);
-#endif /* __HWEMUL_FORMAT__ */
+#endif /* __HWSTUB_FORMAT__ */
diff --git a/utils/hwstub/stmp/hwemul.db b/utils/hwstub/stmp/hwstub.db
index 7a6f930f57..1a085da50a 100644
--- a/utils/hwstub/stmp/hwemul.db
+++ b/utils/hwstub/stmp/hwstub.db
@@ -20,12 +20,12 @@
****************************************************************************/
sources
{
- hwemul = "hwemul.elf";
+ hwstub = "hwstub.elf";
}
section(0)
{
- load hwemul;
- jump hwemul(1);
+ load hwstub;
+ jump hwstub(1);
}
diff --git a/utils/hwstub/stmp/hwemul.lds b/utils/hwstub/stmp/hwstub.lds
index 7e3ac747a2..61504a3e75 100644
--- a/utils/hwstub/stmp/hwemul.lds
+++ b/utils/hwstub/stmp/hwstub.lds
@@ -38,6 +38,7 @@ SECTIONS
{
oc_codestart = .;
*(.text*)
+ *(.icode*)
*(.data*)
*(.rodata*)
} > OCRAM
diff --git a/utils/hwstub/stmp/link.lds b/utils/hwstub/stmp/link.lds
deleted file mode 100644
index 97b259955f..0000000000
--- a/utils/hwstub/stmp/link.lds
+++ /dev/null
@@ -1,49 +0,0 @@
-
-ENTRY(start)
-OUTPUT_FORMAT(elf32-littlearm)
-OUTPUT_ARCH(arm)
-STARTUP(crt0.o)
-
-
-
-MEMORY
-{
- OCRAM : ORIGIN = 0, LENGTH = 0x8000
-}
-
-SECTIONS
-{
- .octext :
- {
- oc_codestart = .;
- *(.text*)
- *(.data*)
- *(.rodata*)
- } > OCRAM
-
- .bss (NOLOAD) :
- {
- bss_start = .;
- *(.bss)
- bss_end = .;
- } > OCRAM
-
- .stack (NOLOAD) :
- {
- oc_codeend = .;
- oc_stackstart = .;
- . += 0x1000;
- oc_stackend = .;
- oc_bufferstart = .;
- } > OCRAM
-
- .ocend (0 + 0x8000) (NOLOAD) :
- {
- oc_bufferend = .;
- } > OCRAM
-
- /DISCARD/ :
- {
- *(.eh_frame)
- }
-}
diff --git a/utils/hwstub/stmp/logf.h b/utils/hwstub/stmp/logf.h
index 5aa882a630..48c8c2c9b9 100644
--- a/utils/hwstub/stmp/logf.h
+++ b/utils/hwstub/stmp/logf.h
@@ -18,8 +18,8 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_LOGF__
-#define __HWEMUL_LOGF__
+#ifndef __HWSTUB_LOGF__
+#define __HWSTUB_LOGF__
#include "stddef.h"
#include <stdarg.h>
@@ -28,4 +28,4 @@ void enable_logf(bool en);
void logf(const char *fmt, ...);
size_t logf_readback(char *buf, size_t max_size);
-#endif /* __HWEMUL_LOGF__ */
+#endif /* __HWSTUB_LOGF__ */
diff --git a/utils/hwstub/stmp/main.c b/utils/hwstub/stmp/main.c
index 09bb6c7714..845f3842ea 100644
--- a/utils/hwstub/stmp/main.c
+++ b/utils/hwstub/stmp/main.c
@@ -34,118 +34,20 @@ extern unsigned char oc_bufferend[];
/**
*
- * Pin control
+ * Global
*
*/
-#define HW_PINCTRL_BASE 0x80018000
-
-#define HW_PINCTRL_CTRL (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x0))
-#define HW_PINCTRL_MUXSEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x100 + (i) * 0x10))
-#define HW_PINCTRL_DRIVE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x200 + (i) * 0x10))
-#ifdef HAVE_STMP3700
-#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x300 + (i) * 0x10))
-#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
-#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
-#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
-#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
-#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
-#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
-#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
-#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
-#else
-#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
-#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
-#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
-#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
-#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
-#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
-#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
-#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
-#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xc00 + (i) * 0x10))
-#endif
-
-#define PINCTRL_FUNCTION_MAIN 0
-#define PINCTRL_FUNCTION_ALT1 1
-#define PINCTRL_FUNCTION_ALT2 2
-#define PINCTRL_FUNCTION_GPIO 3
-
-#define PINCTRL_DRIVE_4mA 0
-#define PINCTRL_DRIVE_8mA 1
-#define PINCTRL_DRIVE_12mA 2
-#define PINCTRL_DRIVE_16mA 3 /* not available on all pins */
-
-typedef void (*pin_irq_cb_t)(int bank, int pin);
-
-static inline void imx233_pinctrl_init(void)
+enum stmp_family_t
{
- __REG_CLR(HW_PINCTRL_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
-}
-
-static inline void imx233_set_pin_drive_strength(unsigned bank, unsigned pin, unsigned strength)
-{
- __REG_CLR(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = 3 << (4 * (pin % 8));
- __REG_SET(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = strength << (4 * (pin % 8));
-}
-
-static inline void imx233_enable_gpio_output(unsigned bank, unsigned pin, bool enable)
-{
- if(enable)
- __REG_SET(HW_PINCTRL_DOE(bank)) = 1 << pin;
- else
- __REG_CLR(HW_PINCTRL_DOE(bank)) = 1 << pin;
-}
-
-static inline void imx233_enable_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool enable)
-{
- if(enable)
- __REG_SET(HW_PINCTRL_DOE(bank)) = pin_mask;
- else
- __REG_CLR(HW_PINCTRL_DOE(bank)) = pin_mask;
-}
-
-static inline void imx233_set_gpio_output(unsigned bank, unsigned pin, bool value)
-{
- if(value)
- __REG_SET(HW_PINCTRL_DOUT(bank)) = 1 << pin;
- else
- __REG_CLR(HW_PINCTRL_DOUT(bank)) = 1 << pin;
-}
-
-static inline void imx233_set_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool value)
-{
- if(value)
- __REG_SET(HW_PINCTRL_DOUT(bank)) = pin_mask;
- else
- __REG_CLR(HW_PINCTRL_DOUT(bank)) = pin_mask;
-}
-
-static inline uint32_t imx233_get_gpio_input_mask(unsigned bank, uint32_t pin_mask)
-{
- return HW_PINCTRL_DIN(bank) & pin_mask;
-}
-
-static inline void imx233_set_pin_function(unsigned bank, unsigned pin, unsigned function)
-{
- __REG_CLR(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = 3 << (2 * (pin % 16));
- __REG_SET(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = function << (2 * (pin % 16));
-}
-
-static inline void imx233_enable_pin_pullup(unsigned bank, unsigned pin, bool enable)
-{
- if(enable)
- __REG_SET(HW_PINCTRL_PULL(bank)) = 1 << pin;
- else
- __REG_CLR(HW_PINCTRL_PULL(bank)) = 1 << pin;
-}
+ UNKNOWN,
+ STMP3600,
+ STMP3700,
+ STMP3770,
+ STMP3780
+};
-static inline void imx233_enable_pin_pullup_mask(unsigned bank, uint32_t pin_msk, bool enable)
-{
- if(enable)
- __REG_SET(HW_PINCTRL_PULL(bank)) = pin_msk;
- else
- __REG_CLR(HW_PINCTRL_PULL(bank)) = pin_msk;
-}
+enum stmp_family_t g_stmp_family = UNKNOWN;
/**
*
@@ -458,287 +360,38 @@ static void usb_drv_configure_endpoint(int ep_num, int type)
/**
*
- * Clock control
+ * Clkctrl
*
- **/
-#define __CLK_CLKGATE (1 << 31)
-#define __CLK_BUSY (1 << 29)
+ */
#define HW_CLKCTRL_BASE 0x80040000
#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
+#define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */
#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16)
#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18)
-#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20
-#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20)
#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
+#define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31)
-#define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
-#define HW_CLKCTRL_CPU__DIV_CPU_BP 0
-#define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f
-#define HW_CLKCTRL_CPU__INTERRUPT_WAIT (1 << 12)
-#define HW_CLKCTRL_CPU__DIV_XTAL_BP 16
-#define HW_CLKCTRL_CPU__DIV_XTAL_BM (0x3ff << 16)
-#define HW_CLKCTRL_CPU__DIV_XTAL_FRAC_EN (1 << 26)
-#define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28)
-
-#define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
-#define HW_CLKCTRL_HBUS__DIV_BP 0
-#define HW_CLKCTRL_HBUS__DIV_BM 0x1f
-#define HW_CLKCTRL_HBUS__DIV_FRAC_EN (1 << 5)
-#define HW_CLKCTRL_HBUS__SLOW_DIV_BP 16
-#define HW_CLKCTRL_HBUS__SLOW_DIV_BM (0x7 << 16)
-#define HW_CLKCTRL_HBUS__AUTO_SLOW_MODE (1 << 20)
-
-#define HW_CLKCTRL_XBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
-#define HW_CLKCTRL_XBUS__DIV_BP 0
-#define HW_CLKCTRL_XBUS__DIV_BM 0x3ff
-#define HW_CLKCTRL_XBUS__BUSY (1 << 31)
-
-#define HW_CLKCTRL_XTAL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x50))
-#define HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE (1 << 26)
-#define HW_CLKCTRL_XTAL__DRI_CLK24M_GATE (1 << 28)
-#define HW_CLKCTRL_XTAL__PWM_CLK24M_GATE (1 << 29)
-#define HW_CLKCTRL_XTAL__FILT_CLK24M_GATE (1 << 30)
-
-#define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60))
-#define HW_CLKCTRL_PIX__DIV_BP 0
-#define HW_CLKCTRL_PIX__DIV_BM 0xfff
-
-#define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
-#define HW_CLKCTRL_SSP__DIV_BP 0
-#define HW_CLKCTRL_SSP__DIV_BM 0x1ff
-
-#define HW_CLKCTRL_EMI (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xa0))
-#define HW_CLKCTRL_EMI__DIV_EMI_BP 0
-#define HW_CLKCTRL_EMI__DIV_EMI_BM 0x3f
-#define HW_CLKCTRL_EMI__DIV_XTAL_BP 8
-#define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8)
-#define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28)
-#define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30)
-#define HW_CLKCTRL_EMI__CLKGATE (1 << 31)
-
-#ifdef HAVE_STMP3770
-#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xe0))
-#else
-#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110))
-#endif
-#define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1)
-#define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5)
-#define HW_CLKCTRL_CLKSEQ__BYPASS_EMI (1 << 6)
-#define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7)
-
-#ifdef HAVE_STMP3770
-#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xd0))
-#else
-#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0))
-#endif
-#define HW_CLKCTRL_FRAC_CPU (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf0))
-#define HW_CLKCTRL_FRAC_EMI (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf1))
-#define HW_CLKCTRL_FRAC_PIX (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf2))
-#define HW_CLKCTRL_FRAC_IO (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf3))
-#define HW_CLKCTRL_FRAC_XX__XXDIV_BM 0x3f
-#define HW_CLKCTRL_FRAC_XX__XX_STABLE (1 << 6)
-#define HW_CLKCTRL_FRAC_XX__CLKGATEXX (1 << 7)
-
-#define HW_CLKCTRL_RESET (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x120))
-#define HW_CLKCTRL_RESET_CHIP 0x2
-#define HW_CLKCTRL_RESET_DIG 0x1
-
-/**
- *
- * DMA
- *
- */
-
-/********
- * APHB *
- ********/
-
-#define HW_APBH_BASE 0x80004000
-
-/* APHB channels */
-#define HW_APBH_SSP(ssp) ssp
-
-#define HW_APBH_CTRL0 (*(volatile uint32_t *)(HW_APBH_BASE + 0x0))
-#define HW_APBH_CTRL0__FREEZE_CHANNEL(i) (1 << (i))
-#define HW_APBH_CTRL0__CLKGATE_CHANNEL(i) (1 << ((i) + 8))
-#define HW_APBH_CTRL0__RESET_CHANNEL(i) (1 << ((i) + 16))
-#define HW_APBH_CTRL0__APB_BURST4_EN (1 << 28)
-#define HW_APBH_CTRL0__APB_BURST8_EN (1 << 29)
-
-#define HW_APBH_CTRL1 (*(volatile uint32_t *)(HW_APBH_BASE + 0x10))
-#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
-#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
-
-#define HW_APBH_CTRL2 (*(volatile uint32_t *)(HW_APBH_BASE + 0x20))
-#define HW_APBH_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
-#define HW_APBH_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
-
-#define HW_APBH_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x40 + 0x70 * (i)))
-
-#define HW_APBH_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x50 + 0x70 * (i)))
-
-#define HW_APBH_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x60 + 0x70 * (i)))
-
-#define HW_APBH_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x70 + 0x70 * (i)))
-
-#define HW_APBH_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x80 + 0x70 * (i)))
-
-#define HW_APBH_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x90 + 0x70 * (i)))
-
-#define HW_APBH_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0xa0 + 0x70 * (i)))
-#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BP 0
-#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BM 0xffff
-#define HW_APBH_CHx_DEBUG2__APB_BYTES_BP 16
-#define HW_APBH_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
-
-/********
- * APHX *
- ********/
-
-/* APHX channels */
-#define HW_APBX_AUDIO_ADC 0
-#define HW_APBX_AUDIO_DAC 1
-#define HW_APBX_I2C 3
-
-#define HW_APBX_BASE 0x80024000
-
-#define HW_APBX_CTRL0 (*(volatile uint32_t *)(HW_APBX_BASE + 0x0))
-
-#define HW_APBX_CTRL1 (*(volatile uint32_t *)(HW_APBX_BASE + 0x10))
-#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
-#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
-
-#define HW_APBX_CTRL2 (*(volatile uint32_t *)(HW_APBX_BASE + 0x20))
-#define HW_APBX_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
-#define HW_APBX_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
+/* STMP3600 only */
+#define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
+#define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0
+#define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff
+#define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30)
-#define HW_APBX_CHANNEL_CTRL (*(volatile uint32_t *)(HW_APBX_BASE + 0x30))
-#define HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(i) (1 << (i))
-#define HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(i) (1 << ((i) + 16))
+/* STMP3600 */
+#define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
-#define HW_APBX_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x100 + (i) * 0x70))
+/* STMP3600 only */
+#define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
+#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0
+#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff
-#define HW_APBX_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x110 + (i) * 0x70))
-
-#define HW_APBX_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x120 + (i) * 0x70))
-
-#define HW_APBX_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x130 + (i) * 0x70))
-
-#define HW_APBX_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x140 + (i) * 0x70))
-
-#define HW_APBX_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x150 + (i) * 0x70))
-
-#define HW_APBX_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x160 + (i) * 0x70))
-#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BP 0
-#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BM 0xffff
-#define HW_APBX_CHx_DEBUG2__APB_BYTES_BP 16
-#define HW_APBX_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
-
-/**********
- * COMMON *
- **********/
-
-struct apb_dma_command_t
-{
- struct apb_dma_command_t *next;
- uint32_t cmd;
- void *buffer;
- /* PIO words follow */
-};
-
-#define APBH_DMA_CHANNEL(i) i
-#define APBX_DMA_CHANNEL(i) ((i) | 0x10)
-#define APB_IS_APBX_CHANNEL(x) ((x) & 0x10)
-#define APB_GET_DMA_CHANNEL(x) ((x) & 0xf)
-
-#define APB_SSP(ssp) APBH_DMA_CHANNEL(HW_APBH_SSP(ssp))
-#define APB_AUDIO_ADC APBX_DMA_CHANNEL(HW_APBX_AUDIO_ADC)
-#define APB_AUDIO_DAC APBX_DMA_CHANNEL(HW_APBX_AUDIO_DAC)
-#define APB_I2C APBX_DMA_CHANNEL(HW_APBX_I2C)
-
-#define HW_APB_CHx_CMD__COMMAND_BM 0x3
-#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0
-#define HW_APB_CHx_CMD__COMMAND__WRITE 1
-#define HW_APB_CHx_CMD__COMMAND__READ 2
-#define HW_APB_CHx_CMD__COMMAND__SENSE 3
-#define HW_APB_CHx_CMD__CHAIN (1 << 2)
-#define HW_APB_CHx_CMD__IRQONCMPLT (1 << 3)
-/* those two are only available on APHB */
-#define HW_APBH_CHx_CMD__NANDLOCK (1 << 4)
-#define HW_APBH_CHx_CMD__NANDWAIT4READY (1 << 5)
-#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6)
-#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7)
-/* An errata advise not to use it */
-//#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
-#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000
-#define HW_APB_CHx_CMD__CMDWORDS_BP 12
-#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000
-#define HW_APB_CHx_CMD__XFER_COUNT_BP 16
-/* For software use */
-#define HW_APB_CHx_CMD__UNUSED_BP 8
-#define HW_APB_CHx_CMD__UNUSED_BM (0xf << 8)
-#define HW_APB_CHx_CMD__UNUSED_MAGIC (0xa << 8)
-
-#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000
-#define HW_APB_CHx_SEMA__PHORE_BP 16
-
-/* A single descriptor cannot transfer more than 2^16 bytes */
-#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16)
-
-static void imx233_dma_init(void)
-{
- __REG_CLR(HW_APBH_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
- __REG_CLR(HW_APBX_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
-}
-
-static void imx233_dma_reset_channel(unsigned chan)
-{
- volatile uint32_t *ptr;
- uint32_t bm;
- if(APB_IS_APBX_CHANNEL(chan))
- {
- ptr = &HW_APBX_CHANNEL_CTRL;
- bm = HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
- }
- else
- {
- ptr = &HW_APBH_CTRL0;
- bm = HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
- }
- __REG_SET(*ptr) = bm;
- /* wait for end of reset */
- while(*ptr & bm)
- ;
-}
-
-static void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
-{
- if(APB_IS_APBX_CHANNEL(chan))
- {
- HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
- HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
- }
- else
- {
- HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
- HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
- }
-}
-
-static void imx233_dma_wait_completion(unsigned chan)
-{
- volatile uint32_t *sema;
- if(APB_IS_APBX_CHANNEL(chan))
- sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
- else
- sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
-
- while(*sema & HW_APB_CHx_SEMA__PHORE_BM)
- ;
-}
+/* STMP3600 only */
+#define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
+#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30)
+#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31)
/**
*
@@ -751,8 +404,6 @@ static void imx233_dma_wait_completion(unsigned chan)
#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
-#define HW_DIGCTL_HCLKCOUNT (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x20))
-
#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
@@ -786,7 +437,6 @@ static void udelay(unsigned us)
/* USB Phy */
#define HW_USBPHY_BASE 0x8007C000
#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
-#define HW_USBPHY_PWD__ALL (7 << 10 | 0xf << 17)
#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
@@ -852,17 +502,9 @@ struct dcp_packet_t
*
*/
-void memcpy(uint8_t *dst, const uint8_t *src, uint32_t length)
-{
- for(uint32_t i = 0; i < length; i++)
- dst[i] = src[i];
-}
-
-void memset(uint8_t *dst, uint8_t fill, uint32_t length)
-{
- for(uint32_t i = 0; i < length; i++)
- dst[i] = fill;
-}
+void memcpy(void *dest, const void *src, size_t n);
+void memmove(void *dest, const void *src, size_t n);
+void memset(void *dst, int value, size_t n);
/**
*
@@ -880,9 +522,9 @@ static struct usb_device_descriptor __attribute__((aligned(2)))
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
- .idVendor = HWEMUL_USB_VID,
- .idProduct = HWEMUL_USB_PID,
- .bcdDevice = HWEMUL_VERSION_MAJOR << 8 | HWEMUL_VERSION_MINOR,
+ .idVendor = HWSTUB_USB_VID,
+ .idProduct = HWSTUB_USB_PID,
+ .bcdDevice = HWSTUB_VERSION_MAJOR << 8 | HWSTUB_VERSION_MINOR,
.iManufacturer = 1,
.iProduct = 2,
.iSerialNumber = 3,
@@ -913,9 +555,9 @@ static struct usb_interface_descriptor __attribute__((aligned(2)))
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 3,
- .bInterfaceClass = HWEMUL_CLASS,
- .bInterfaceSubClass = HWEMUL_SUBCLASS,
- .bInterfaceProtocol = HWEMUL_PROTOCOL,
+ .bInterfaceClass = HWSTUB_CLASS,
+ .bInterfaceSubClass = HWSTUB_SUBCLASS,
+ .bInterfaceProtocol = HWSTUB_PROTOCOL,
.iInterface = 4
};
@@ -966,9 +608,9 @@ static struct usb_string_descriptor __attribute__((aligned(2)))
28,
USB_DT_STRING,
{'A', 'c', 'i', 'd', ' ',
- '0' + (HWEMUL_VERSION_MAJOR >> 4), '0' + (HWEMUL_VERSION_MAJOR & 0xf), '.',
- '0' + (HWEMUL_VERSION_MINOR >> 4), '0' + (HWEMUL_VERSION_MINOR & 0xf), '.',
- '0' + (HWEMUL_VERSION_REV >> 4), '0' + (HWEMUL_VERSION_REV & 0xf) }
+ '0' + (HWSTUB_VERSION_MAJOR >> 4), '0' + (HWSTUB_VERSION_MAJOR & 0xf), '.',
+ '0' + (HWSTUB_VERSION_MINOR >> 4), '0' + (HWSTUB_VERSION_MINOR & 0xf), '.',
+ '0' + (HWSTUB_VERSION_REV >> 4), '0' + (HWSTUB_VERSION_REV & 0xf) }
};
/* this is stringid #0: languages supported */
@@ -1138,9 +780,9 @@ static void handle_std_req(struct usb_ctrlrequest *req)
struct usb_resp_info_version_t g_version =
{
- .major = HWEMUL_VERSION_MAJOR,
- .minor = HWEMUL_VERSION_MINOR,
- .revision = HWEMUL_VERSION_REV
+ .major = HWSTUB_VERSION_MAJOR,
+ .minor = HWSTUB_VERSION_MINOR,
+ .revision = HWSTUB_VERSION_REV
};
struct usb_resp_info_layout_t g_layout;
@@ -1149,8 +791,8 @@ struct usb_resp_info_stmp_t g_stmp;
struct usb_resp_info_features_t g_features =
{
- .feature_mask = HWEMUL_FEATURE_LOG | HWEMUL_FEATURE_MEM |
- HWEMUL_FEATURE_CALL | HWEMUL_FEATURE_JUMP | HWEMUL_FEATURE_AES_OTP
+ .feature_mask = HWSTUB_FEATURE_LOG | HWSTUB_FEATURE_MEM |
+ HWSTUB_FEATURE_CALL | HWSTUB_FEATURE_JUMP | HWSTUB_FEATURE_AES_OTP
};
static void fill_layout_info(void)
@@ -1177,21 +819,21 @@ static void handle_get_info(struct usb_ctrlrequest *req)
int size = 0;
switch(req->wIndex)
{
- case HWEMUL_INFO_VERSION:
+ case HWSTUB_INFO_VERSION:
ptr = &g_version;
size = sizeof(g_version);
break;
- case HWEMUL_INFO_LAYOUT:
+ case HWSTUB_INFO_LAYOUT:
fill_layout_info();
ptr = &g_layout;
size = sizeof(g_layout);
break;
- case HWEMUL_INFO_STMP:
+ case HWSTUB_INFO_STMP:
fill_stmp_info();
ptr = &g_stmp;
size = sizeof(g_stmp);
break;
- case HWEMUL_INFO_FEATURES:
+ case HWSTUB_INFO_FEATURES:
ptr = &g_features;
size = sizeof(g_features);
break;
@@ -1249,17 +891,22 @@ static void handle_call_jump(struct usb_ctrlrequest *req)
{
uint32_t addr = req->wValue | req->wIndex << 16;
- if(req->bRequest == HWEMUL_CALL)
+ if(req->bRequest == HWSTUB_CALL)
((void (*)(void))addr)();
else
+ {
+ /* disconnect to make sure usb/dma won't interfere */
+ REG_USBCMD &= ~USBCMD_RUN;
+ REG_USBCMD |= USBCMD_CTRL_RESET;
asm volatile("bx %0\n" : : "r" (addr) : "memory");
+ }
}
static void do_aes_otp(void *buffer, unsigned length, unsigned params)
{
static struct dcp_packet_t dcp_packet;
- bool encrypt = !!(params & HWEMUL_AES_OTP_ENCRYPT);
+ bool encrypt = !!(params & HWSTUB_AES_OTP_ENCRYPT);
/* reset DCP */
__REG_SET(HW_DCP_CTRL) = 0x80000000;
/* clear clock gate */
@@ -1307,20 +954,20 @@ static void handle_class_dev_req(struct usb_ctrlrequest *req)
{
switch(req->bRequest)
{
- case HWEMUL_GET_INFO:
+ case HWSTUB_GET_INFO:
handle_get_info(req);
break;
- case HWEMUL_GET_LOG:
+ case HWSTUB_GET_LOG:
handle_get_log(req);
break;
- case HWEMUL_RW_MEM:
+ case HWSTUB_RW_MEM:
handle_rw_mem(req);
break;
- case HWEMUL_CALL:
- case HWEMUL_JUMP:
+ case HWSTUB_CALL:
+ case HWSTUB_JUMP:
handle_call_jump(req);
break;
- case HWEMUL_AES_OTP:
+ case HWSTUB_AES_OTP:
handle_aes_otp(req);
break;
default:
@@ -1348,19 +995,68 @@ static void handle_class_req(struct usb_ctrlrequest *req)
void main(uint32_t arg)
{
usb_buffer_size = oc_buffersize;
-
- logf("hwemul %d.%d.%d\n", HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR,
- HWEMUL_VERSION_REV);
+
+ logf("hwstub %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR,
+ HWSTUB_VERSION_REV);
logf("argument: 0x%08x\n", arg);
+ /* detect family */
+ uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
+ if(product_code >= 0x3600 && product_code < 0x3700)
+ {
+ logf("identified STMP3600 family\n");
+ g_stmp_family = STMP3600;
+ }
+ else if(product_code == 0x3700)
+ {
+ logf("identified STMP3700 family\n");
+ g_stmp_family = STMP3700;
+ }
+ else if(product_code == 0x37b0)
+ {
+ logf("identified STMP3770 family\n");
+ g_stmp_family = STMP3770;
+ }
+ else if(product_code == 0x3780)
+ {
+ logf("identified STMP3780 family\n");
+ g_stmp_family = STMP3780;
+ }
+ else
+ logf("cannot identify family: 0x%x\n", product_code);
+
/* we don't know if USB was connected or not. In USB recovery mode it will
* but in other cases it might not be. In doubt, disconnect */
REG_USBCMD &= ~USBCMD_RUN;
+ if(g_stmp_family == STMP3600)
+ {
+ /* CPU clock is always derived from PLL, if we switch to PLL, cpu will
+ * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed
+ * (1.2MHz) for a safe transition */
+ HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400;
+ /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the
+ * switch so lower XBUS too */
+ HW_CLKCTRL_XBUSCLKCTRL = 20;
+ /* Power PLL */
+ __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
+ HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480;
+ /* Wait lock */
+ while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK));
+ /* Switch to PLL source */
+ __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS;
+ /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */
+ HW_CLKCTRL_CPUCLKCTRL = 7;
+ HW_CLKCTRL_HBUSCLKCTRL = 7;
+ HW_CLKCTRL_XBUSCLKCTRL = 1;
+ __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE;
+ __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE;
+ }
+ else
+ __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
/* enable USB PHY PLL */
__REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
/* power up USB PHY */
__REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
- //__REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
HW_USBPHY_PWD = 0;
/* enable USB controller */
__REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
@@ -1382,7 +1078,7 @@ void main(uint32_t arg)
REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
/* run! */
REG_USBCMD |= USBCMD_RUN;
-
+
while(1)
{
/* wait for setup */
diff --git a/utils/hwstub/stmp/memcpy.S b/utils/hwstub/stmp/memcpy.S
new file mode 100644
index 0000000000..2a55fb5656
--- /dev/null
+++ b/utils/hwstub/stmp/memcpy.S
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ * This file was originally part of the GNU C Library
+ * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)
+ * Adapted for Rockbox by Daniel Ankers
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull lsr
+#define push lsl
+#else
+#define pull lsl
+#define push lsr
+#endif
+
+/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
+
+ .section .icode,"ax",%progbits
+
+ .align 2
+ .global memcpy
+ .type memcpy,%function
+
+memcpy:
+ stmfd sp!, {r0, r4, lr}
+
+ subs r2, r2, #4
+ blt 8f
+ ands ip, r0, #3
+ bne 9f
+ ands ip, r1, #3
+ bne 10f
+
+1: subs r2, r2, #(28)
+ stmfd sp!, {r5 - r8}
+ blt 5f
+
+2:
+3:
+4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ subs r2, r2, #32
+ stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ bge 3b
+
+5: ands ip, r2, #28
+ rsb ip, ip, #32
+ addne pc, pc, ip @ C is always clear here
+ b 7f
+6: nop
+ ldr r3, [r1], #4
+ ldr r4, [r1], #4
+ ldr r5, [r1], #4
+ ldr r6, [r1], #4
+ ldr r7, [r1], #4
+ ldr r8, [r1], #4
+ ldr lr, [r1], #4
+
+ add pc, pc, ip
+ nop
+ nop
+ str r3, [r0], #4
+ str r4, [r0], #4
+ str r5, [r0], #4
+ str r6, [r0], #4
+ str r7, [r0], #4
+ str r8, [r0], #4
+ str lr, [r0], #4
+
+7: ldmfd sp!, {r5 - r8}
+
+8: movs r2, r2, lsl #31
+ ldrneb r3, [r1], #1
+ ldrcsb r4, [r1], #1
+ ldrcsb ip, [r1]
+ strneb r3, [r0], #1
+ strcsb r4, [r0], #1
+ strcsb ip, [r0]
+
+ ldmpc regs="r0, r4"
+
+9: rsb ip, ip, #4
+ cmp ip, #2
+ ldrgtb r3, [r1], #1
+ ldrgeb r4, [r1], #1
+ ldrb lr, [r1], #1
+ strgtb r3, [r0], #1
+ strgeb r4, [r0], #1
+ subs r2, r2, ip
+ strb lr, [r0], #1
+ blt 8b
+ ands ip, r1, #3
+ beq 1b
+
+10: bic r1, r1, #3
+ cmp ip, #2
+ ldr lr, [r1], #4
+ beq 17f
+ bgt 18f
+
+
+ .macro forward_copy_shift pull push
+
+ subs r2, r2, #28
+ blt 14f
+
+11: stmfd sp!, {r5 - r9}
+
+12:
+13: ldmia r1!, {r4, r5, r6, r7}
+ mov r3, lr, pull #\pull
+ subs r2, r2, #32
+ ldmia r1!, {r8, r9, ip, lr}
+ orr r3, r3, r4, push #\push
+ mov r4, r4, pull #\pull
+ orr r4, r4, r5, push #\push
+ mov r5, r5, pull #\pull
+ orr r5, r5, r6, push #\push
+ mov r6, r6, pull #\pull
+ orr r6, r6, r7, push #\push
+ mov r7, r7, pull #\pull
+ orr r7, r7, r8, push #\push
+ mov r8, r8, pull #\pull
+ orr r8, r8, r9, push #\push
+ mov r9, r9, pull #\pull
+ orr r9, r9, ip, push #\push
+ mov ip, ip, pull #\pull
+ orr ip, ip, lr, push #\push
+ stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
+ bge 12b
+
+ ldmfd sp!, {r5 - r9}
+
+14: ands ip, r2, #28
+ beq 16f
+
+15: mov r3, lr, pull #\pull
+ ldr lr, [r1], #4
+ subs ip, ip, #4
+ orr r3, r3, lr, push #\push
+ str r3, [r0], #4
+ bgt 15b
+
+16: sub r1, r1, #(\push / 8)
+ b 8b
+
+ .endm
+
+
+ forward_copy_shift pull=8 push=24
+
+17: forward_copy_shift pull=16 push=16
+
+18: forward_copy_shift pull=24 push=8
+
diff --git a/utils/hwstub/stmp/memmove.S b/utils/hwstub/stmp/memmove.S
new file mode 100644
index 0000000000..d8cab048be
--- /dev/null
+++ b/utils/hwstub/stmp/memmove.S
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ * This file was originally part of the GNU C Library
+ * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)
+ * Adapted for Rockbox by Daniel Ankers
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull lsr
+#define push lsl
+#else
+#define pull lsl
+#define push lsr
+#endif
+
+ .text
+
+/*
+ * Prototype: void *memmove(void *dest, const void *src, size_t n);
+ *
+ * Note:
+ *
+ * If the memory regions don't overlap, we simply branch to memcpy which is
+ * normally a bit faster. Otherwise the copy is done going downwards.
+ */
+
+ .section .icode,"ax",%progbits
+
+ .align 2
+ .global memmove
+ .type memmove,%function
+
+memmove:
+
+ subs ip, r0, r1
+ cmphi r2, ip
+ bls memcpy
+
+ stmfd sp!, {r0, r4, lr}
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt 8f
+ ands ip, r0, #3
+ bne 9f
+ ands ip, r1, #3
+ bne 10f
+
+1: subs r2, r2, #(28)
+ stmfd sp!, {r5 - r8}
+ blt 5f
+
+2:
+3:
+4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ subs r2, r2, #32
+ stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
+ bge 3b
+
+5: ands ip, r2, #28
+ rsb ip, ip, #32
+ addne pc, pc, ip @ C is always clear here
+ b 7f
+6: nop
+ ldr r3, [r1, #-4]!
+ ldr r4, [r1, #-4]!
+ ldr r5, [r1, #-4]!
+ ldr r6, [r1, #-4]!
+ ldr r7, [r1, #-4]!
+ ldr r8, [r1, #-4]!
+ ldr lr, [r1, #-4]!
+
+ add pc, pc, ip
+ nop
+ nop
+ str r3, [r0, #-4]!
+ str r4, [r0, #-4]!
+ str r5, [r0, #-4]!
+ str r6, [r0, #-4]!
+ str r7, [r0, #-4]!
+ str r8, [r0, #-4]!
+ str lr, [r0, #-4]!
+
+7: ldmfd sp!, {r5 - r8}
+
+8: movs r2, r2, lsl #31
+ ldrneb r3, [r1, #-1]!
+ ldrcsb r4, [r1, #-1]!
+ ldrcsb ip, [r1, #-1]
+ strneb r3, [r0, #-1]!
+ strcsb r4, [r0, #-1]!
+ strcsb ip, [r0, #-1]
+ ldmpc regs="r0, r4"
+
+9: cmp ip, #2
+ ldrgtb r3, [r1, #-1]!
+ ldrgeb r4, [r1, #-1]!
+ ldrb lr, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ strgeb r4, [r0, #-1]!
+ subs r2, r2, ip
+ strb lr, [r0, #-1]!
+ blt 8b
+ ands ip, r1, #3
+ beq 1b
+
+10: bic r1, r1, #3
+ cmp ip, #2
+ ldr r3, [r1, #0]
+ beq 17f
+ blt 18f
+
+
+ .macro backward_copy_shift push pull
+
+ subs r2, r2, #28
+ blt 14f
+
+11: stmfd sp!, {r5 - r9}
+
+12:
+13: ldmdb r1!, {r7, r8, r9, ip}
+ mov lr, r3, push #\push
+ subs r2, r2, #32
+ ldmdb r1!, {r3, r4, r5, r6}
+ orr lr, lr, ip, pull #\pull
+ mov ip, ip, push #\push
+ orr ip, ip, r9, pull #\pull
+ mov r9, r9, push #\push
+ orr r9, r9, r8, pull #\pull
+ mov r8, r8, push #\push
+ orr r8, r8, r7, pull #\pull
+ mov r7, r7, push #\push
+ orr r7, r7, r6, pull #\pull
+ mov r6, r6, push #\push
+ orr r6, r6, r5, pull #\pull
+ mov r5, r5, push #\push
+ orr r5, r5, r4, pull #\pull
+ mov r4, r4, push #\push
+ orr r4, r4, r3, pull #\pull
+ stmdb r0!, {r4 - r9, ip, lr}
+ bge 12b
+
+ ldmfd sp!, {r5 - r9}
+
+14: ands ip, r2, #28
+ beq 16f
+
+15: mov lr, r3, push #\push
+ ldr r3, [r1, #-4]!
+ subs ip, ip, #4
+ orr lr, lr, r3, pull #\pull
+ str lr, [r0, #-4]!
+ bgt 15b
+
+16: add r1, r1, #(\pull / 8)
+ b 8b
+
+ .endm
+
+
+ backward_copy_shift push=8 pull=24
+
+17: backward_copy_shift push=16 pull=16
+
+18: backward_copy_shift push=24 pull=8
+
+
diff --git a/utils/hwstub/stmp/memset.S b/utils/hwstub/stmp/memset.S
new file mode 100644
index 0000000000..682da874ce
--- /dev/null
+++ b/utils/hwstub/stmp/memset.S
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Thom Johansen
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+
+ .section .icode,"ax",%progbits
+
+ .align 2
+
+/* The following code is based on code found in Linux kernel version 2.6.15.3
+ * linux/arch/arm/lib/memset.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ */
+
+/* This code will align a pointer for memset, if needed */
+1: cmp r2, #4 @ 1 do we have enough
+ blt 5f @ 1 bytes to align with?
+ cmp r3, #2 @ 1
+ strgtb r1, [r0, #-1]! @ 1
+ strgeb r1, [r0, #-1]! @ 1
+ strb r1, [r0, #-1]! @ 1
+ sub r2, r2, r3 @ 1 r2 = r2 - r3
+ b 2f
+
+ .global memset
+ .type memset,%function
+memset:
+ add r0, r0, r2 @ we'll write backwards in memory
+ ands r3, r0, #3 @ 1 unaligned?
+ bne 1b @ 1
+2:
+/*
+ * we know that the pointer in r0 is aligned to a word boundary.
+ */
+ orr r1, r1, r1, lsl #8
+ orr r1, r1, r1, lsl #16
+ mov r3, r1
+ cmp r2, #16
+ blt 5f
+/*
+ * We need an extra register for this loop - save the return address and
+ * use the LR
+ */
+ str lr, [sp, #-4]!
+ mov ip, r1
+ mov lr, r1
+
+3: subs r2, r2, #64
+ stmgedb r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
+ stmgedb r0!, {r1, r3, ip, lr}
+ stmgedb r0!, {r1, r3, ip, lr}
+ stmgedb r0!, {r1, r3, ip, lr}
+ bgt 3b
+ ldrpc cond=eq @ Now <64 bytes to go.
+/*
+ * No need to correct the count; we're only testing bits from now on
+ */
+ tst r2, #32
+ stmnedb r0!, {r1, r3, ip, lr}
+ stmnedb r0!, {r1, r3, ip, lr}
+ tst r2, #16
+ stmnedb r0!, {r1, r3, ip, lr}
+ ldr lr, [sp], #4
+
+5: tst r2, #8
+ stmnedb r0!, {r1, r3}
+ tst r2, #4
+ strne r1, [r0, #-4]!
+/*
+ * When we get here, we've got less than 4 bytes to zero. We
+ * may have an unaligned pointer as well.
+ */
+6: tst r2, #2
+ strneb r1, [r0, #-1]!
+ strneb r1, [r0, #-1]!
+ tst r2, #1
+ strneb r1, [r0, #-1]!
+ bx lr
+.end:
+ .size memset,.end-memset
diff --git a/utils/hwstub/stmp/protocol.h b/utils/hwstub/stmp/protocol.h
index d3ffb6ce00..35510fa9b2 100644
--- a/utils/hwstub/stmp/protocol.h
+++ b/utils/hwstub/stmp/protocol.h
@@ -1 +1 @@
-#include "../hwemul_protocol.h"
+#include "../hwstub_protocol.h"
diff --git a/utils/hwstub/stmp/stddef.h b/utils/hwstub/stmp/stddef.h
index 9d59d2913c..9bfd767750 100644
--- a/utils/hwstub/stmp/stddef.h
+++ b/utils/hwstub/stmp/stddef.h
@@ -18,8 +18,8 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_STDDEF__
-#define __HWEMUL_STDDEF__
+#ifndef __HWSTUB_STDDEF__
+#define __HWSTUB_STDDEF__
#include "stdint.h"
@@ -29,4 +29,4 @@ typedef int32_t ssize_t;
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif /* __HWEMUL_STDDEF__ */
+#endif /* __HWSTUB_STDDEF__ */
diff --git a/utils/hwstub/stmp/string.h b/utils/hwstub/stmp/string.h
index 7ef460ea6e..184144e525 100644
--- a/utils/hwstub/stmp/string.h
+++ b/utils/hwstub/stmp/string.h
@@ -18,8 +18,8 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_STRING__
-#define __HWEMUL_STRING__
+#ifndef __HWSTUB_STRING__
+#define __HWSTUB_STRING__
#include "stddef.h"
@@ -27,4 +27,4 @@ void memset(void *dst, int c, size_t n);
void memcpy(void *dst, const void *src, size_t n);
size_t strlen(const char *s);
-#endif /* __HWEMUL_STRING__ */
+#endif /* __HWSTUB_STRING__ */
diff --git a/utils/hwstub/stmp/system.h b/utils/hwstub/stmp/system.h
index c1babe7d87..e5aea12051 100644
--- a/utils/hwstub/stmp/system.h
+++ b/utils/hwstub/stmp/system.h
@@ -18,8 +18,8 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __HWEMUL_SYSTEM__
-#define __HWEMUL_SYSTEM__
+#ifndef __HWSTUB_SYSTEM__
+#define __HWSTUB_SYSTEM__
#define IRQ_ENABLED 0x00
#define IRQ_DISABLED 0x80
@@ -114,5 +114,5 @@ static inline int disable_interrupt_save(int mask)
return cpsr;
}
-#endif /* __HWEMUL_SYSTEM__ */
+#endif /* __HWSTUB_SYSTEM__ */
diff --git a/utils/hwstub/tools/Makefile b/utils/hwstub/tools/Makefile
index 3466a4e776..6db0c709b1 100644
--- a/utils/hwstub/tools/Makefile
+++ b/utils/hwstub/tools/Makefile
@@ -1,22 +1,38 @@
CC=gcc
-AR=ar
-HWEMUL_LIB_DIR=../lib
-CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWEMUL_LIB_DIR)
-LDFLAGS=`pkg-config --libs libusb-1.0` -lreadline
-EXEC=hwemul_tool
-HWEMUL_LIB=$(HWEMUL_LIB_DIR)/libhwemul.a
+CXX=g++
+LD=g++
+HWSTUB_LIB_DIR=../lib
+REGTOOLS_LIB_DIR=../../regtools/lib
+CFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2`
+CXXFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2`
+LDFLAGS=`pkg-config --libs libusb-1.0` `pkg-config --libs lua5.2` -lreadline -L$(HWSTUB_LIB_DIR) -L$(REGTOOLS_LIB_DIR) -lsocdesc -lhwstub `xml2-config --libs`
+EXEC=hwstub_shell hwstub_load
SRC=$(wildcard *.c)
-OBJ=$(SRC:.c=.o)
+SRCXX=$(wildcard *.cpp)
+OBJ=$(SRC:.c=.o) $(SRCXX:.cpp=.o)
+LIBS=$(HWSTUB_LIB_DIR)/libhwstub.a $(REGTOOLS_LIB_DIR)/libsocdesc.a
all: $(EXEC)
+$(HWSTUB_LIB_DIR)/libhwstub.a:
+ make -C $(HWSTUB_LIB_DIR)
+
+$(REGTOOLS_LIB_DIR)/libsocdesc.a:
+ make -C $(REGTOOLS_LIB_DIR)
+
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
-hwemul_tool: hwemul_tool.o $(HWEMUL_LIB)
- $(CC) -o $@ $^ $(LDFLAGS)
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+hwstub_shell: hwstub_shell.o $(LIBS)
+ $(LD) -o $@ $^ $(LDFLAGS)
+
+hwstub_load: hwstub_load.o $(LIBS)
+ $(LD) -o $@ $^ $(LDFLAGS)
clean:
- rm -rf $(OBJ) $(LIB)
+ rm -rf $(OBJ) $(LIB) $(EXEC)
diff --git a/utils/hwstub/tools/hwemul_tool.c b/utils/hwstub/tools/hwemul_tool.c
deleted file mode 100644
index d75cd7a957..0000000000
--- a/utils/hwstub/tools/hwemul_tool.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2012 by Amaury Pouly
- *
- * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#include "hwemul.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-bool g_quiet = false;
-struct hwemul_device_t hwdev;
-struct hwemul_soc_t *cur_soc = NULL;
-
-void print_log(struct hwemul_device_t *hwdev)
-{
- do
- {
- char buffer[128];
- int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
- if(length <= 0)
- break;
- buffer[length] = 0;
- printf("%s", buffer);
- }while(1);
-}
-
-int print_help()
-{
- printf("Commands:\n");
- printf(" help\t\tDisplay this help\n");
- printf(" call <addr>\tCall address <addr>\n");
- printf(" quit\t\tQuit this session\n");
- printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
- printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
- printf(" read <regname>\tRead a register by name\n");
- printf(" read <regname>.<field>\tRead a register field by name\n");
- printf(" soc <socname>\tSelect the soc description to use\n");
- printf(" write <value> <regname>\tWrite a register by name\n");
- printf(" write <value <regname>.<field>\tWrite a register field by name\n");
- printf(" NOTE: if the register is SCT variant, no read is performed.\n");
- return 1;
-}
-
-int syntax_error(char *str)
-{
- printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
- return 1;
-}
-
-int parse_uint32(char *str, uint32_t *u)
-{
- char *end;
- *u = strtoul(str, &end, 0);
- return *end == 0;
-}
-
-int do_call(uint32_t a)
-{
- hwemul_call(&hwdev, a);
- return 1;
-}
-
-int parse_call()
-{
- char *arg = strtok(NULL, " ");
- uint32_t addr;
- if(arg && parse_uint32(arg, &addr))
- return do_call(addr);
- else
- return syntax_error(arg);
-}
-
-int do_read32(uint32_t a)
-{
- uint32_t val;
- if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
- printf("%#x = %#x\n", a, val);
- else
- printf("read error at %#x\n", a);
- return 1;
-}
-
-int parse_read32()
-{
- char *arg = strtok(NULL, " ");
- uint32_t addr;
- if(arg && parse_uint32(arg, &addr))
- return do_read32(addr);
- else
- return syntax_error(arg);
-}
-
-int do_write32(uint32_t val, uint32_t a)
-{
- if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
- printf("data written\n");
- else
- printf("write error at %#x\n", a);
- return 1;
-}
-
-int parse_write32()
-{
- char *arg = strtok(NULL, " ");
- uint32_t val;
- if(!arg || !parse_uint32(arg, &val))
- return syntax_error(arg);
- uint32_t addr;
- arg = strtok(NULL, " ");
- if(arg && parse_uint32(arg, &addr))
- return do_write32(val, addr);
- else
- return syntax_error(arg);
-}
-
-struct hwemul_soc_t *find_soc_by_name(const char *soc)
-{
- struct hwemul_soc_list_t *list = hwemul_get_soc_list();
- for(size_t i = 0; i < list->nr_socs; i++)
- if(strcmp(soc, list->socs[i]->name) == 0)
- return list->socs[i];
- return NULL;
-}
-
-struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
-{
- for(size_t i = 0; i < soc->nr_regs; i++)
- if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
- return soc->regs_by_name[i];
- return NULL;
-}
-
-struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
-{
- for(size_t i = 0; i < reg->nr_fields; i++)
- if(strcmp(field, reg->fields_by_name[i]->name) == 0)
- return reg->fields_by_name[i];
- return NULL;
-}
-
-
-int do_read(char *regname)
-{
- char *dot = strchr(regname, '.');
- if(dot != NULL)
- *dot++ = 0;
- if(cur_soc == NULL)
- {
- printf("No soc selected!\n");
- return 1;
- }
- struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
- if(reg == NULL)
- {
- printf("no reg '%s' found\n", regname);
- return 1;
- }
- uint32_t val;
- if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
- {
- printf("read error at %#x\n", reg->addr);
- return 1;
- }
- if(dot)
- {
- struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
- if(field == NULL)
- {
- printf("no field '%s' found\n", dot);
- return 1;
- }
- val >>= field->first_bit;
- val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
- printf("%s.%s = %#x\n", regname, dot, val);
- }
- else
- printf("%s = %#x\n", regname, val);
- return 1;
-}
-
-int parse_read()
-{
- char *arg = strtok(NULL, " ");
- if(arg)
- return do_read(arg);
- else
- return syntax_error(arg);
-}
-
-int do_soc(char *soc)
-{
- struct hwemul_soc_t *s = find_soc_by_name(soc);
- if(s == NULL)
- printf("no soc '%s' found\n", soc);
- else
- cur_soc = s;
- return 1;
-}
-
-int parse_soc()
-{
- char *arg = strtok(NULL, " ");
- if(arg)
- return do_soc(arg);
- else
- return syntax_error(arg);
-}
-
-int do_write(uint32_t val, char *regname)
-{
- char *dot = strchr(regname, '.');
- if(dot != NULL)
- *dot++ = 0;
- if(cur_soc == NULL)
- {
- printf("No soc selected!\n");
- return 1;
- }
- struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
- int is_sct = 0;
- uint32_t addr_off = 0;
- if(reg == NULL)
- {
- size_t len = strlen(regname);
- /* try SCT variant */
- if(strcmp(regname + len - 4, "_SET") == 0)
- addr_off = 4;
- else if(strcmp(regname + len - 4, "_CLR") == 0)
- addr_off = 8;
- else if(strcmp(regname + len - 4, "_TOG") == 0)
- addr_off = 12;
- else
- {
- printf("no reg '%s' found\n", regname);
- return 1;
- }
- is_sct = 1;
- regname[len - 4] = 0;
- reg = find_reg_by_name(cur_soc, regname);
- if(reg == NULL)
- {
- printf("no reg '%s' found\n", regname);
- return 1;
- }
- }
- if(dot)
- {
- struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
- if(field == NULL)
- {
- printf("no field '%s' found\n", dot);
- return 1;
- }
- uint32_t actual_val = 0;
- if(!is_sct)
- {
- if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
- {
- printf("read error at %#x\n", reg->addr);
- return 1;
- }
- printf("read %#x at %#x\n", actual_val, reg->addr);
- }
- uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
- printf("mask=%#x\n", mask);
- val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
- }
- printf("write %#x to %#x\n", val, reg->addr + addr_off);
- if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
- {
- printf("write error at %#x\n", reg->addr);
- return 1;
- }
- return 1;
-}
-
-int parse_write()
-{
- char *arg = strtok(NULL, " ");
- uint32_t val;
- if(!arg || !parse_uint32(arg, &val))
- return syntax_error(arg);
- arg = strtok(NULL, " ");
- if(arg)
- return do_write(val, arg);
- else
- return syntax_error(arg);
-}
-
-int parse_command(char *cmd)
-{
- if(strcmp(cmd, "help") == 0)
- return print_help();
- if(strcmp(cmd, "quit") == 0)
- return 0;
- if(strcmp(cmd, "call") == 0)
- return parse_call();
- if(strcmp(cmd, "read32") == 0)
- return parse_read32();
- if(strcmp(cmd, "write32") == 0)
- return parse_write32();
- if(strcmp(cmd, "read") == 0)
- return parse_read();
- if(strcmp(cmd, "soc") == 0)
- return parse_soc();
- if(strcmp(cmd, "write") == 0)
- return parse_write();
- return syntax_error(cmd);
-}
-
-void interactive_mode(void)
-{
- rl_bind_key('\t', rl_complete);
- while(1)
- {
- char *input = readline("> ");
- if(!input)
- break;
- add_history(input);
- int ret = parse_command(input);
- free(input);
- if(ret == 0)
- break;
- }
-}
-
-void usage(void)
-{
- printf("hwemul_tool, compiled with hwemul %d.%d.%d\n",
- HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, HWEMUL_VERSION_REV);
- printf("available soc descriptions:");
- for(unsigned i = 0; i < hwemul_get_soc_list()->nr_socs; i++)
- printf(" %s", hwemul_get_soc_list()->socs[i]->name);
- printf("\n");
- printf("usage: hwemul_tool [options]\n");
- printf("options:\n");
- printf(" --help/-?\tDisplay this help\n");
- printf(" --quiet/-q\tQuiet non-command messages\n");
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- while(1)
- {
- static struct option long_options[] =
- {
- {"help", no_argument, 0, '?'},
- {"quiet", no_argument, 0, 'q'},
- {0, 0, 0, 0}
- };
-
- int c = getopt_long(argc, argv, "?q", long_options, NULL);
- if(c == -1)
- break;
- switch(c)
- {
- case -1:
- break;
- case 'q':
- g_quiet = true;
- break;
- case '?':
- usage();
- break;
- default:
- abort();
- }
- }
-
- if(argc - optind != 0)
- {
- usage();
- return 1;
- }
-
- libusb_context *ctx;
- libusb_init(&ctx);
- libusb_set_debug(ctx, 3);
-
- if(!g_quiet)
- printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID, HWEMUL_USB_PID);
-
- libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
- HWEMUL_USB_VID, HWEMUL_USB_PID);
- if(handle == NULL)
- {
- printf("No device found\n");
- return 1;
- }
-
- libusb_device *mydev = libusb_get_device(handle);
- if(!g_quiet)
- {
- printf("device found at %d:%d\n",
- libusb_get_bus_number(mydev),
- libusb_get_device_address(mydev));
- }
- hwdev.handle = handle;
- if(hwemul_probe(&hwdev))
- {
- printf("Cannot probe device!\n");
- return 1;
- }
-
- struct usb_resp_info_version_t ver;
- int ret = hwemul_get_info(&hwdev, HWEMUL_INFO_VERSION, &ver, sizeof(ver));
- if(ret != sizeof(ver))
- {
- printf("Cannot get version!\n");
- goto Lerr;
- }
- if(!g_quiet)
- printf("Device version: %d.%d.%d\n", ver.major, ver.minor, ver.revision);
-
- struct usb_resp_info_layout_t layout;
- ret = hwemul_get_info(&hwdev, HWEMUL_INFO_LAYOUT, &layout, sizeof(layout));
- if(ret != sizeof(layout))
- {
- printf("Cannot get layout: %d\n", ret);
- goto Lerr;
- }
- if(!g_quiet)
- {
- printf("Device layout:\n");
- printf(" Code: 0x%x (0x%x)\n", layout.oc_code_start, layout.oc_code_size);
- printf(" Stack: 0x%x (0x%x)\n", layout.oc_stack_start, layout.oc_stack_size);
- printf(" Buffer: 0x%x (0x%x)\n", layout.oc_buffer_start, layout.oc_buffer_size);
- }
-
- struct usb_resp_info_features_t features;
- ret = hwemul_get_info(&hwdev, HWEMUL_INFO_FEATURES, &features, sizeof(features));
- if(ret != sizeof(features))
- {
- printf("Cannot get features: %d\n", ret);
- goto Lerr;
- }
- if(!g_quiet)
- {
- printf("Device features:");
- if(features.feature_mask & HWEMUL_FEATURE_LOG)
- printf(" log");
- if(features.feature_mask & HWEMUL_FEATURE_MEM)
- printf(" mem");
- if(features.feature_mask & HWEMUL_FEATURE_CALL)
- printf(" call");
- if(features.feature_mask & HWEMUL_FEATURE_JUMP)
- printf(" jump");
- if(features.feature_mask & HWEMUL_FEATURE_AES_OTP)
- printf(" aes_otp");
- printf("\n");
- }
-
- struct usb_resp_info_stmp_t stmp;
- ret = hwemul_get_info(&hwdev, HWEMUL_INFO_STMP, &stmp, sizeof(stmp));
- if(ret != sizeof(stmp))
- {
- printf("Cannot get stmp: %d\n", ret);
- goto Lerr;
- }
- if(!g_quiet)
- {
- printf("Device stmp:\n");
- printf(" chip ID: %x (%s)\n", stmp.chipid,hwemul_get_product_string(&stmp));
- printf(" revision: %d (%s)\n", stmp.rev, hwemul_get_rev_string(&stmp));
- printf(" supported: %d\n", stmp.is_supported);
- }
-
- if(!g_quiet)
- {
- void *rom = malloc(64 * 1024);
- ret = hwemul_rw_mem(&hwdev, 1, 0xc0000000, rom, 64 * 1024);
- if(ret != 64 * 1024)
- {
- printf("Cannot read ROM: %d\n", ret);
- goto Lerr;
- }
-
- printf("ROM successfully read!\n");
- FILE *f = fopen("rom.bin", "wb");
- fwrite(rom, 64 * 1024, 1, f);
- fclose(f);
- }
-
- if(!g_quiet)
- {
- struct
- {
- uint8_t iv[16];
- uint8_t data[16];
- } __attribute__((packed)) dcp_test;
-
- for(int i = 0; i < 16; i++)
- dcp_test.iv[i] = rand();
- for(int i = 0; i < 16; i++)
- dcp_test.data[i] = rand();
- printf("DCP\n");
- printf(" IN\n");
- printf(" IV:");
- for(int i = 0; i < 16; i++)
- printf(" %02x", dcp_test.iv[i]);
- printf("\n");
- printf(" IV:");
- for(int i = 0; i < 16; i++)
- printf(" %02x", dcp_test.data[i]);
- printf("\n");
-
- if(!hwemul_aes_otp(&hwdev, &dcp_test, sizeof(dcp_test), HWEMUL_AES_OTP_ENCRYPT))
- {
- printf(" OUT\n");
- printf(" IV:");
- for(int i = 0; i < 16; i++)
- printf(" %02x", dcp_test.iv[i]);
- printf("\n");
- printf(" IV:");
- for(int i = 0; i < 16; i++)
- printf(" %02x", dcp_test.data[i]);
- printf("\n");
- }
- else
- printf("DCP error!\n");
- }
-
- if(!g_quiet)
- printf("Starting interactive session. Type 'help' to get help.\n");
-
- interactive_mode();
-
- Lerr:
- if(features.feature_mask & HWEMUL_FEATURE_LOG)
- {
- if(!g_quiet)
- printf("Device log:\n");
- print_log(&hwdev);
- }
- hwemul_release(&hwdev);
- return 1;
-}
diff --git a/utils/hwstub/tools/hwstub_load.cpp b/utils/hwstub/tools/hwstub_load.cpp
new file mode 100644
index 0000000000..d58eb83396
--- /dev/null
+++ b/utils/hwstub/tools/hwstub_load.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 by Amaury Pouly
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "hwstub.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <ctype.h>
+
+struct player_info_t
+{
+ const char *name;
+ const char *username;
+ int modelnum;
+};
+
+enum image_type_t
+{
+ IT_RAW,
+ IT_ROCKBOX,
+ IT_DETECT,
+ /* positive values reserved for rockbox-specific models */
+};
+
+struct player_info_t players[] =
+{
+ { "zenv", "Zen V", 85 },
+ { "zmoz", "Zen Mozaic", 87 },
+ { "zen", "Zen", 88 },
+ { "zxfi", "Zen X-Fi", 86 },
+ { NULL, 0 },
+};
+
+enum image_type_t detect_type(unsigned char *buffer, size_t size)
+{
+ if(size < 8)
+ return IT_RAW;
+ int player;
+ for(player = 0; players[player].name; player++)
+ if(memcmp(buffer + 4, players[player].name, 4) == 0)
+ break;
+ if(players[player].name == NULL)
+ return IT_RAW;
+ unsigned long checksum = players[player].modelnum;
+ for(size_t i = 8; i < size; i++)
+ checksum += buffer[i];
+ unsigned long expected = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
+ if(checksum != expected)
+ return IT_RAW;
+ return IT_ROCKBOX;
+}
+
+const char *get_player_name(unsigned char *buffer)
+{
+ for(int player = 0; players[player].name; player++)
+ if(memcmp(buffer, players[player].name, 4) == 0)
+ return players[player].username;
+ return NULL;
+}
+
+bool could_be_rockbox(unsigned char *buffer, size_t size)
+{
+ /* usually target use 3 or 4 digits */
+ if(size >= 8 && isprint(buffer[4]) && isprint(buffer[5]) && isprint(buffer[6]) &&
+ (isprint(buffer[7]) || buffer[7] == 0))
+ {
+ unsigned long checksum = 0;
+ for(size_t i = 8; i < size; i++)
+ checksum += buffer[i];
+ unsigned long expected = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
+ unsigned long expected_modelnm = expected - checksum;
+ if(expected_modelnm < 150)
+ fprintf(stderr, "This file looks like a valid rockbox image but I don't know this player: %.4s (modelnum=%ld)\n",
+ buffer + 4, expected_modelnm);
+ else
+ fprintf(stderr, "This file could be a valid rockbox image but I don't know this player and the checksum is strange: %.4s\n",
+ buffer + 4);
+ return true;
+ }
+ else
+ return false;
+}
+
+void usage(void)
+{
+ printf("usage: hwstub_load [options] <addr> <file>\n");
+ printf("options:\n");
+ printf(" --help/-? Display this help\n");
+ printf(" --quiet/-q Quiet output\n");
+ printf(" --type/-t <t> Override file type\n");
+ printf("file types:\n");
+ printf(" raw Load a raw binary blob\n");
+ printf(" rockbox Load a rockbox image produced by scramble\n");
+ printf(" detect Try to guess the format\n");
+ printf("known players:");
+ for(int i = 0; players[i].name; i++)
+ printf(" %s", players[i].name);
+ printf("\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ bool quiet = false;
+ struct hwstub_device_t hwdev;
+ enum image_type_t type = IT_DETECT;
+
+ // parse command line
+ while(1)
+ {
+ static struct option long_options[] =
+ {
+ {"help", no_argument, 0, '?'},
+ {"quiet", no_argument, 0, 'q'},
+ {"type", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int c = getopt_long(argc, argv, "?qt:", long_options, NULL);
+ if(c == -1)
+ break;
+ switch(c)
+ {
+ case -1:
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case '?':
+ usage();
+ break;
+ case 't':
+ if(strcmp(optarg, "raw") == 0)
+ type = IT_RAW;
+ else if(strcmp(optarg, "rockbox") == 0)
+ type = IT_ROCKBOX;
+ else if(strcmp(optarg, "detect") == 0)
+ type = IT_DETECT;
+ else
+ {
+ fprintf(stderr, "Unknown file type '%s'\n", optarg);
+ return 1;
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+
+ if(optind + 2 != argc)
+ usage();
+
+ char *end;
+ unsigned long addr = strtoul(argv[optind], &end, 0);
+ if(*end)
+ {
+ fprintf(stderr, "Invalid load address\n");
+ return 2;
+ }
+
+ FILE *f = fopen(argv[optind + 1], "rb");
+ if(f == NULL)
+ {
+ fprintf(stderr, "Cannot open file for reading: %m\n");
+ return 3;
+ }
+ fseek(f, 0, SEEK_END);
+ size_t size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ unsigned char *buffer = (unsigned char*)malloc(size);
+ fread(buffer, size, 1, f);
+ fclose(f);
+
+ if(type == IT_ROCKBOX || type == IT_DETECT)
+ {
+ enum image_type_t det = detect_type(buffer, size);
+ if(type == IT_ROCKBOX && det != IT_ROCKBOX)
+ {
+ if(!could_be_rockbox(buffer, size))
+ fprintf(stderr, "This file does not appear to be valid rockbox image.\n");
+ return 4;
+ }
+ if(type == IT_DETECT && det == IT_RAW)
+ could_be_rockbox(buffer, size);
+ type = det;
+ if(type == IT_ROCKBOX)
+ {
+ if(!quiet)
+ printf("Rockox image is for player %s (%.4s)\n", get_player_name(buffer + 4), buffer + 4);
+ memmove(buffer, buffer + 8, size - 8);
+ size -= 8;
+ }
+ }
+
+ if(!quiet)
+ {
+ if(type == IT_RAW)
+ printf("Loading raw image at %#lx\n", addr);
+ else
+ printf("Loading rockbox image at %#lx\n", addr);
+ }
+
+ // create usb context
+ libusb_context *ctx;
+ libusb_init(&ctx);
+ libusb_set_debug(ctx, 3);
+
+ // look for device
+ if(!quiet)
+ printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID);
+
+ libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
+ HWSTUB_USB_VID, HWSTUB_USB_PID);
+ if(handle == NULL)
+ {
+ fprintf(stderr, "No device found\n");
+ return 1;
+ }
+
+ // admin stuff
+ libusb_device *mydev = libusb_get_device(handle);
+ if(!quiet)
+ {
+ printf("device found at %d:%d\n",
+ libusb_get_bus_number(mydev),
+ libusb_get_device_address(mydev));
+ }
+ hwdev.handle = handle;
+ if(hwstub_probe(&hwdev))
+ {
+ fprintf(stderr, "Cannot probe device!\n");
+ return 1;
+ }
+
+ // get hwstub information
+ struct usb_resp_info_version_t hwdev_ver;
+ int ret = hwstub_get_info(&hwdev, HWSTUB_INFO_VERSION, &hwdev_ver, sizeof(hwdev_ver));
+ if(ret != sizeof(hwdev_ver))
+ {
+ fprintf(stderr, "Cannot get version!\n");
+ goto Lerr;
+ }
+ if(hwdev_ver.major != HWSTUB_VERSION_MAJOR || hwdev_ver.minor < HWSTUB_VERSION_MINOR)
+ {
+ printf("Warning: this tool is possibly incompatible with your device:\n");
+ printf("Device version: %d.%d.%d\n", hwdev_ver.major, hwdev_ver.minor, hwdev_ver.revision);
+ printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
+ }
+
+ // get features
+ struct usb_resp_info_features_t hwdev_features;
+ ret = hwstub_get_info(&hwdev, HWSTUB_INFO_FEATURES, &hwdev_features, sizeof(hwdev_features));
+ if(ret != sizeof(hwdev_features))
+ {
+ fprintf(stderr, "Cannot get features: %d\n", ret);
+ goto Lerr;
+ }
+ if(!(hwdev_features.feature_mask & HWSTUB_RW_MEM))
+ {
+ fprintf(stderr, "Device doesn't support R/W commands\n");
+ goto Lerr;
+ }
+ if(!(hwdev_features.feature_mask & HWSTUB_JUMP))
+ {
+ fprintf(stderr, "Device doesn't support jump commands\n");
+ goto Lerr;
+ }
+ ret = hwstub_rw_mem(&hwdev, 0, addr, buffer, size);
+ if(ret != (int)size)
+ {
+ fprintf(stderr, "Image write failed\n");
+ goto Lerr;
+ }
+ hwstub_jump(&hwdev, addr);
+
+ hwstub_release(&hwdev);
+ return 0;
+
+ Lerr:
+ // display log if handled
+ if(hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
+ {
+ fprintf(stderr, "Device log:\n");
+ do
+ {
+ char buffer[128];
+ int length = hwstub_get_log(&hwdev, buffer, sizeof(buffer) - 1);
+ if(length <= 0)
+ break;
+ buffer[length] = 0;
+ fprintf(stderr, "%s", buffer);
+ }while(1);
+ }
+ hwstub_release(&hwdev);
+ return 1;
+}
+
diff --git a/utils/hwstub/tools/hwstub_shell.cpp b/utils/hwstub/tools/hwstub_shell.cpp
new file mode 100644
index 0000000000..58147319e0
--- /dev/null
+++ b/utils/hwstub/tools/hwstub_shell.cpp
@@ -0,0 +1,873 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2012 by Amaury Pouly
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "hwstub.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <lua.hpp>
+#include "soc_desc.hpp"
+
+#if LUA_VERSION_NUM < 502
+#warning You need at least lua 5.2
+#endif
+
+/**
+ * Global variables
+ */
+bool g_quiet = false;
+struct hwstub_device_t g_hwdev;
+struct usb_resp_info_version_t g_hwdev_ver;
+struct usb_resp_info_layout_t g_hwdev_layout;
+struct usb_resp_info_features_t g_hwdev_features;
+struct usb_resp_info_stmp_t g_hwdev_stmp;
+lua_State *g_lua;
+
+/**
+ * hw specific
+ */
+
+void print_log(struct hwstub_device_t *hwdev)
+{
+ do
+ {
+ char buffer[128];
+ int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1);
+ if(length <= 0)
+ break;
+ buffer[length] = 0;
+ printf("%s", buffer);
+ }while(1);
+}
+
+/**
+ * Lua specific
+ */
+int my_lua_help(lua_State *state)
+{
+ bool has_sub = false;
+ // implement help() in C so that we do not rely on the init to implement it
+ // help can take optional arguments
+ int n = lua_gettop(state);
+
+ lua_getglobal(state, "hwstub");
+ if(!lua_istable(state, -1))
+ goto Lerr;
+ lua_getfield(state, -1, "help");
+ if(!lua_istable(state, -1))
+ goto Lerr;
+
+ for(int i = 1; i <= n; i++)
+ {
+ lua_pushvalue(state, i);
+ lua_gettable(state, -2);
+ if(lua_isnil(state, -1))
+ {
+ printf("I don't know subtopic '%s'!\n", lua_tostring(state, i));
+ return 0;
+ }
+ if(!lua_istable(state, -1))
+ {
+ printf("Subtopic '%s' is not a table!\n", lua_tostring(state, i));
+ return 0;
+ }
+ }
+
+ printf("================[ HELP ");
+ for(int i = 1; i <= n; i++)
+ printf("> %s ", lua_tostring(state, i));
+ printf("]================\n");
+
+ lua_pushnil(state);
+ while(lua_next(state, -2))
+ {
+ // key is at -2 and value at -1
+ if(lua_isstring(state, -1))
+ printf("%s\n", lua_tostring(state, -1));
+ else if(lua_istable(state, -1))
+ has_sub = true;
+ // pop value but keep key
+ lua_pop(state, 1);
+ }
+
+ if(has_sub)
+ {
+ printf("\n");
+ printf("You can get more information on the following subtopics:\n");
+ lua_pushnil(state);
+ while(lua_next(state, -2))
+ {
+ // key is at -2 and value at -1
+ if(lua_istable(state, -1))
+ printf("* %s\n", lua_tostring(state, -2));
+ // pop value but keep key
+ lua_pop(state, 1);
+ }
+ }
+ printf("================[ STOP ]================\n");
+
+ return 0;
+
+ Lerr:
+ printf("There is a problem with the Lua context. Help is expected to be in hwstub.help\n");
+ printf("You must have messed badly the environment.\n");
+ return 0;
+}
+
+typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr);
+typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val);
+
+soc_word_t hw_read8(lua_State *state, soc_addr_t addr)
+{
+ uint8_t u;
+ if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to read8 @ %p", addr);
+ return u;
+}
+
+soc_word_t hw_read16(lua_State *state, soc_addr_t addr)
+{
+ uint16_t u;
+ if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to read16 @ %p", addr);
+ return u;
+}
+
+soc_word_t hw_read32(lua_State *state, soc_addr_t addr)
+{
+ uint32_t u;
+ if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to read32 @ %p", addr);
+ return u;
+}
+
+void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val)
+{
+ uint8_t u = val;
+ if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to write8 @ %p", addr);
+}
+
+void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val)
+{
+ uint16_t u = val;
+ if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to write16 @ %p", addr);
+}
+
+void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val)
+{
+ uint32_t u = val;
+ if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
+ luaL_error(state, "fail to write32 @ %p", addr);
+}
+
+int my_lua_readn(lua_State *state)
+{
+ hw_readn_fn_t fn = (hw_readn_fn_t)lua_touserdata(state, lua_upvalueindex(1));
+ int n = lua_gettop(state);
+ if(n != 1)
+ luaL_error(state, "readn takes a single argument");
+ lua_pushunsigned(state, fn(state, luaL_checkunsigned(state, 1)));
+ return 1;
+}
+
+int my_lua_writen(lua_State *state)
+{
+ hw_writen_fn_t fn = (hw_writen_fn_t)lua_touserdata(state, lua_upvalueindex(1));
+ int n = lua_gettop(state);
+ if(n != 2)
+ luaL_error(state, "writen takes two arguments");
+ fn(state, luaL_checkunsigned(state, 1), luaL_checkunsigned(state, 2));
+ return 0;
+}
+
+int my_lua_printlog(lua_State *state)
+{
+ print_log(&g_hwdev);
+ return 0;
+}
+
+bool my_lua_import_hwstub()
+{
+ int oldtop = lua_gettop(g_lua);
+
+ lua_newtable(g_lua); // hwstub
+
+ lua_newtable(g_lua); // options
+ lua_pushboolean(g_lua, g_quiet);
+ lua_setfield(g_lua, -2, "quiet");
+ lua_setfield(g_lua, -2, "options");
+
+ lua_newtable(g_lua); // dev
+ lua_newtable(g_lua); // version
+ lua_pushinteger(g_lua, g_hwdev_ver.major);
+ lua_setfield(g_lua, -2, "major");
+ lua_pushinteger(g_lua, g_hwdev_ver.minor);
+ lua_setfield(g_lua, -2, "minor");
+ lua_pushinteger(g_lua, g_hwdev_ver.revision);
+ lua_setfield(g_lua, -2, "revision");
+ lua_setfield(g_lua, -2, "version");
+
+ lua_newtable(g_lua); // layout
+ lua_newtable(g_lua); // ocram
+ lua_newtable(g_lua); // code
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_code_start);
+ lua_setfield(g_lua, -2, "start");
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_code_size);
+ lua_setfield(g_lua, -2, "size");
+ lua_setfield(g_lua, -2, "code");
+ lua_newtable(g_lua); // stack
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_start);
+ lua_setfield(g_lua, -2, "start");
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_size);
+ lua_setfield(g_lua, -2, "size");
+ lua_setfield(g_lua, -2, "stack");
+ lua_newtable(g_lua); // buffer
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_start);
+ lua_setfield(g_lua, -2, "start");
+ lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_size);
+ lua_setfield(g_lua, -2, "size");
+ lua_setfield(g_lua, -2, "buffer");
+ lua_setfield(g_lua, -2, "ocram");
+ lua_setfield(g_lua, -2, "layout");
+
+ lua_newtable(g_lua); // stmp
+ lua_pushinteger(g_lua, g_hwdev_stmp.chipid);
+ lua_setfield(g_lua, -2, "chipid");
+ lua_pushinteger(g_lua, g_hwdev_stmp.rev);
+ lua_setfield(g_lua, -2, "rev");
+ lua_setfield(g_lua, -2, "stmp");
+
+ lua_newtable(g_lua); // features
+ lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG));
+ lua_setfield(g_lua, -2, "log");
+ lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_MEM));
+ lua_setfield(g_lua, -2, "mem");
+ lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_CALL));
+ lua_setfield(g_lua, -2, "call");
+ lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_JUMP));
+ lua_setfield(g_lua, -2, "jump");
+ lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_AES_OTP));
+ lua_setfield(g_lua, -2, "aes_otp");
+ lua_setfield(g_lua, -2, "features");
+
+ lua_pushlightuserdata(g_lua, (void *)&hw_read8);
+ lua_pushcclosure(g_lua, my_lua_readn, 1);
+ lua_setfield(g_lua, -2, "read8");
+ lua_pushlightuserdata(g_lua, (void *)&hw_read16);
+ lua_pushcclosure(g_lua, my_lua_readn, 1);
+ lua_setfield(g_lua, -2, "read16");
+ lua_pushlightuserdata(g_lua, (void *)&hw_read32);
+ lua_pushcclosure(g_lua, my_lua_readn, 1);
+ lua_setfield(g_lua, -2, "read32");
+
+ lua_pushlightuserdata(g_lua, (void *)&hw_write8);
+ lua_pushcclosure(g_lua, my_lua_writen, 1);
+ lua_setfield(g_lua, -2, "write8");
+ lua_pushlightuserdata(g_lua, (void *)&hw_write16);
+ lua_pushcclosure(g_lua, my_lua_writen, 1);
+ lua_setfield(g_lua, -2, "write16");
+ lua_pushlightuserdata(g_lua, (void *)&hw_write32);
+ lua_pushcclosure(g_lua, my_lua_writen, 1);
+ lua_setfield(g_lua, -2, "write32");
+ lua_pushcclosure(g_lua, my_lua_printlog, 0);
+ lua_setfield(g_lua, -2, "print_log");
+
+ lua_setfield(g_lua, -2, "dev");
+
+ lua_newtable(g_lua); // host
+ lua_newtable(g_lua); // version
+ lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR);
+ lua_setfield(g_lua, -2, "major");
+ lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR);
+ lua_setfield(g_lua, -2, "minor");
+ lua_pushinteger(g_lua, HWSTUB_VERSION_REV);
+ lua_setfield(g_lua, -2, "revision");
+ lua_setfield(g_lua, -2, "version");
+ lua_setfield(g_lua, -2, "host");
+
+ lua_newtable(g_lua); // soc
+ lua_setfield(g_lua, -2, "soc");
+
+ lua_newtable(g_lua); // help
+ lua_pushinteger(g_lua, 1);
+ lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands.");
+ lua_settable(g_lua, -3);
+ lua_pushinteger(g_lua, 2);
+ lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on.");
+ lua_settable(g_lua, -3);
+ lua_pushinteger(g_lua, 3);
+ lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z).");
+ lua_settable(g_lua, -3);
+ lua_pushinteger(g_lua, 4);
+ lua_pushstring(g_lua, "Example: help(\"hwstub\").");
+ lua_settable(g_lua, -3);
+ lua_setfield(g_lua, -2, "help");
+
+ lua_setglobal(g_lua, "hwstub");
+
+ lua_pushcfunction(g_lua, my_lua_help);
+ lua_setglobal(g_lua, "help");
+
+ if(lua_gettop(g_lua) != oldtop)
+ {
+ printf("internal error: unbalanced my_lua_import_soc");
+ return false;
+ }
+ return true;
+}
+
+int my_lua_read_reg(lua_State *state)
+{
+ int n = lua_gettop(state);
+ if(n != 0)
+ luaL_error(state, "read() takes no argument");
+ soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
+ lua_pushunsigned(state, hw_read32(state, addr));
+ return 1;
+}
+
+int my_lua_write_reg(lua_State *state)
+{
+ int n = lua_gettop(state);
+ if(n != 1)
+ luaL_error(state, "write() takes one argument");
+ soc_word_t val = luaL_checkunsigned(state, 1);
+ soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
+ hw_write32(state, addr, val);
+ return 0;
+}
+
+int my_lua_read_field(lua_State *state)
+{
+ int n = lua_gettop(state);
+ if(n != 0)
+ luaL_error(state, "read() takes no argument");
+ soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
+ soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
+ soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
+ lua_pushunsigned(state, (hw_read32(state, addr) >> shift) & mask);
+ return 1;
+}
+
+int my_lua_write_field(lua_State *state)
+{
+ int n = lua_gettop(state);
+ if(n != 0 && n!= 1)
+ luaL_error(state, "write() takes one or no argument");
+ soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
+ soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
+ soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
+ bool is_sct = lua_toboolean(state, lua_upvalueindex(5));
+
+ soc_word_t value = mask;
+ if(n == 1)
+ {
+ if(!lua_isnumber(state, 1) && lua_isstring(state, 1))
+ {
+ lua_pushvalue(state, lua_upvalueindex(4));
+ lua_pushvalue(state, 1);
+ lua_gettable(state, -2);
+ if(lua_isnil(state, -1))
+ luaL_error(state, "field has no value %s", lua_tostring(state, 1));
+ value = luaL_checkunsigned(state, -1);
+ lua_pop(state, 2);
+ }
+ else
+ value = luaL_checkunsigned(state, 1);
+ value &= mask;
+ }
+
+ if(!is_sct)
+ value = value << shift | (hw_read32(state, addr) & ~(mask << shift));
+ else
+ value <<= shift;
+
+ hw_write32(state, addr, value);
+ return 0;
+}
+
+void my_lua_create_field(soc_addr_t addr, const soc_reg_field_t& field, bool sct)
+{
+ lua_newtable(g_lua);
+
+ lua_pushstring(g_lua, field.name.c_str());
+ lua_setfield(g_lua, -2, "name");
+
+ lua_pushunsigned(g_lua, addr);
+ lua_setfield(g_lua, -2, "addr");
+
+ lua_pushboolean(g_lua, sct);
+ lua_setfield(g_lua, -2, "sct");
+
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_setfield(g_lua, -2, "first_bit");
+
+ lua_pushunsigned(g_lua, field.last_bit);
+ lua_setfield(g_lua, -2, "last_bit");
+
+ lua_pushunsigned(g_lua, field.bitmask());
+ lua_setfield(g_lua, -2, "bitmask");
+
+ soc_word_t local_bitmask = field.bitmask() >> field.first_bit;
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_setfield(g_lua, -2, "local_bitmask");
+
+ lua_pushunsigned(g_lua, addr);
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_pushcclosure(g_lua, my_lua_read_field, 3);
+ lua_setfield(g_lua, -2, "read");
+
+ lua_pushunsigned(g_lua, addr);
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_pushvalue(g_lua, -4);
+ lua_pushboolean(g_lua, false);
+ lua_pushcclosure(g_lua, my_lua_write_field, 5);
+ lua_setfield(g_lua, -2, "write");
+
+ if(sct)
+ {
+ lua_pushunsigned(g_lua, addr + 4);
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_pushvalue(g_lua, -4);
+ lua_pushboolean(g_lua, true);
+ lua_pushcclosure(g_lua, my_lua_write_field, 5);
+ lua_setfield(g_lua, -2, "set");
+
+ lua_pushunsigned(g_lua, addr + 8);
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_pushvalue(g_lua, -4);
+ lua_pushboolean(g_lua, true);
+ lua_pushcclosure(g_lua, my_lua_write_field, 5);
+ lua_setfield(g_lua, -2, "clr");
+
+ lua_pushunsigned(g_lua, addr + 12);
+ lua_pushunsigned(g_lua, field.first_bit);
+ lua_pushunsigned(g_lua, local_bitmask);
+ lua_pushvalue(g_lua, -4);
+ lua_pushboolean(g_lua, true);
+ lua_pushcclosure(g_lua, my_lua_write_field, 5);
+ lua_setfield(g_lua, -2, "tog");
+ }
+
+ for(size_t i = 0; i < field.value.size(); i++)
+ {
+ lua_pushunsigned(g_lua, field.value[i].value);
+ lua_setfield(g_lua, -2, field.value[i].name.c_str());
+ }
+}
+
+void my_lua_create_reg(soc_addr_t addr, size_t index, const soc_reg_t& reg)
+{
+ lua_newtable(g_lua);
+
+ lua_pushstring(g_lua, reg.addr[index].name.c_str());
+ lua_setfield(g_lua, -2, "name");
+
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
+ lua_setfield(g_lua, -2, "addr");
+
+ lua_pushboolean(g_lua, !!(reg.flags & REG_HAS_SCT));
+ lua_setfield(g_lua, -2, "sct");
+
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
+ lua_pushcclosure(g_lua, my_lua_read_reg, 1);
+ lua_setfield(g_lua, -2, "read");
+
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
+ lua_pushcclosure(g_lua, my_lua_write_reg, 1);
+ lua_setfield(g_lua, -2, "write");
+
+ if(reg.flags & REG_HAS_SCT)
+ {
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 4);
+ lua_pushcclosure(g_lua, my_lua_write_reg, 1);
+ lua_setfield(g_lua, -2, "set");
+
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 8);
+ lua_pushcclosure(g_lua, my_lua_write_reg, 1);
+ lua_setfield(g_lua, -2, "clr");
+
+ lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 12);
+ lua_pushcclosure(g_lua, my_lua_write_reg, 1);
+ lua_setfield(g_lua, -2, "tog");
+ }
+
+ for(size_t i = 0; i < reg.field.size(); i++)
+ {
+ my_lua_create_field(addr + reg.addr[index].addr, reg.field[i],
+ reg.flags & REG_HAS_SCT);
+ lua_setfield(g_lua, -2, reg.field[i].name.c_str());
+ }
+}
+
+void my_lua_create_dev(size_t index, const soc_dev_t& dev)
+{
+ lua_newtable(g_lua);
+
+ lua_pushstring(g_lua, dev.addr[index].name.c_str());
+ lua_setfield(g_lua, -2, "name");
+
+ lua_pushunsigned(g_lua, dev.addr[index].addr);
+ lua_setfield(g_lua, -2, "addr");
+
+ for(size_t i = 0; i < dev.reg.size(); i++)
+ {
+ bool table = dev.reg[i].addr.size() > 1;
+ if(table)
+ lua_newtable(g_lua);
+ else
+ lua_pushnil(g_lua);
+
+ for(size_t k = 0; k < dev.reg[i].addr.size(); k++)
+ {
+ my_lua_create_reg(dev.addr[index].addr, k, dev.reg[i]);
+ if(table)
+ {
+ lua_pushinteger(g_lua, k);
+ lua_pushvalue(g_lua, -2);
+ lua_settable(g_lua, -4);
+ }
+ lua_setfield(g_lua, -3, dev.reg[i].addr[k].name.c_str());
+ }
+
+ if(table)
+ lua_setfield(g_lua, -2, dev.reg[i].name.c_str());
+ else
+ lua_pop(g_lua, 1);
+ }
+}
+
+bool my_lua_import_soc(const soc_t& soc)
+{
+ int oldtop = lua_gettop(g_lua);
+
+ lua_getglobal(g_lua, "hwstub");
+ lua_getfield(g_lua, -1, "soc");
+
+ lua_newtable(g_lua);
+
+ lua_pushstring(g_lua, soc.name.c_str());
+ lua_setfield(g_lua, -2, "name");
+
+ lua_pushstring(g_lua, soc.desc.c_str());
+ lua_setfield(g_lua, -2, "desc");
+
+ for(size_t i = 0; i < soc.dev.size(); i++)
+ {
+ bool table = soc.dev[i].addr.size() > 1;
+ if(table)
+ lua_newtable(g_lua);
+ else
+ lua_pushnil(g_lua);
+
+ for(size_t k = 0; k < soc.dev[i].addr.size(); k++)
+ {
+ my_lua_create_dev(k, soc.dev[i]);
+ if(table)
+ {
+ lua_pushinteger(g_lua, k + 1);
+ lua_pushvalue(g_lua, -2);
+ lua_settable(g_lua, -4);
+ }
+ lua_setfield(g_lua, -3, soc.dev[i].addr[k].name.c_str());
+ }
+
+ if(table)
+ lua_setfield(g_lua, -2, soc.dev[i].name.c_str());
+ else
+ lua_pop(g_lua, 1);
+ }
+
+ lua_setfield(g_lua, -2, soc.name.c_str());
+
+ lua_pop(g_lua, 2);
+
+ if(lua_gettop(g_lua) != oldtop)
+ {
+ printf("internal error: unbalanced my_lua_import_soc\n");
+ return false;
+ }
+ return true;
+}
+
+bool my_lua_import_soc(const std::vector< soc_t >& socs)
+{
+ for(size_t i = 0; i < socs.size(); i++)
+ {
+ if(!g_quiet)
+ printf("importing %s...\n", socs[i].name.c_str());
+ if(!my_lua_import_soc(socs[i]))
+ return false;
+ }
+ return true;
+}
+
+/**
+ * glue
+ */
+
+void usage(void)
+{
+ printf("hwstub_tool, compiled with hwstub %d.%d.%d\n",
+ HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
+ printf("\n");
+ printf("usage: hwstub_tool [options] <soc desc files>\n");
+ printf("options:\n");
+ printf(" --help/-?\tDisplay this help\n");
+ printf(" --quiet/-q\tQuiet non-command messages\n");
+ printf(" -i <init>\tSet lua init file (default is init.lua)\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ const char *lua_init = "init.lua";
+ // parse command line
+ while(1)
+ {
+ static struct option long_options[] =
+ {
+ {"help", no_argument, 0, '?'},
+ {"quiet", no_argument, 0, 'q'},
+ {0, 0, 0, 0}
+ };
+
+ int c = getopt_long(argc, argv, "?qi:", long_options, NULL);
+ if(c == -1)
+ break;
+ switch(c)
+ {
+ case -1:
+ break;
+ case 'q':
+ g_quiet = true;
+ break;
+ case '?':
+ usage();
+ break;
+ case 'i':
+ lua_init = optarg;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ // load register descriptions
+ std::vector< soc_t > socs;
+ for(int i = optind; i < argc; i++)
+ if(!soc_desc_parse_xml(argv[i], socs))
+ {
+ printf("Cannot load description '%s'\n", argv[i]);
+ return 2;
+ }
+
+ // create usb context
+ libusb_context *ctx;
+ libusb_init(&ctx);
+ libusb_set_debug(ctx, 3);
+
+ // look for device
+ if(!g_quiet)
+ printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID);
+
+ libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
+ HWSTUB_USB_VID, HWSTUB_USB_PID);
+ if(handle == NULL)
+ {
+ printf("No device found\n");
+ return 1;
+ }
+
+ // admin stuff
+ libusb_device *mydev = libusb_get_device(handle);
+ if(!g_quiet)
+ {
+ printf("device found at %d:%d\n",
+ libusb_get_bus_number(mydev),
+ libusb_get_device_address(mydev));
+ }
+ g_hwdev.handle = handle;
+ if(hwstub_probe(&g_hwdev))
+ {
+ printf("Cannot probe device!\n");
+ return 1;
+ }
+
+ // get hwstub information
+ int ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
+ if(ret != sizeof(g_hwdev_ver))
+ {
+ printf("Cannot get version!\n");
+ goto Lerr;
+ }
+ if(g_hwdev_ver.major != HWSTUB_VERSION_MAJOR || g_hwdev_ver.minor < HWSTUB_VERSION_MINOR)
+ {
+ printf("Warning: this tool is possibly incompatible with your device:\n");
+ printf("Device version: %d.%d.%d\n", g_hwdev_ver.major, g_hwdev_ver.minor, g_hwdev_ver.revision);
+ printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
+ }
+
+ // get memory layout information
+ ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
+ if(ret != sizeof(g_hwdev_layout))
+ {
+ printf("Cannot get layout: %d\n", ret);
+ goto Lerr;
+ }
+
+ // get features
+ ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_FEATURES, &g_hwdev_features, sizeof(g_hwdev_features));
+ if(ret != sizeof(g_hwdev_features))
+ {
+ printf("Cannot get features: %d\n", ret);
+ goto Lerr;
+ }
+
+ // get STMP specific information
+ ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
+ if(ret != sizeof(g_hwdev_stmp))
+ {
+ printf("Cannot get stmp: %d\n", ret);
+ goto Lerr;
+ }
+
+ // dump ROM
+ if(!g_quiet)
+ {
+ void *rom = malloc(64 * 1024);
+ ret = hwstub_rw_mem(&g_hwdev, 1, 0xc0000000, rom, 64 * 1024);
+ if(ret != 64 * 1024)
+ {
+ printf("Cannot read ROM: %d\n", ret);
+ goto Lerr;
+ }
+
+ printf("ROM successfully read!\n");
+ FILE *f = fopen("rom.bin", "wb");
+ fwrite(rom, 64 * 1024, 1, f);
+ fclose(f);
+ }
+
+ // test DCP
+#if 0
+ if(!g_quiet)
+ {
+ struct
+ {
+ uint8_t iv[16];
+ uint8_t data[16];
+ } __attribute__((packed)) dcp_test;
+
+ for(int i = 0; i < 16; i++)
+ dcp_test.iv[i] = rand();
+ for(int i = 0; i < 16; i++)
+ dcp_test.data[i] = rand();
+ printf("DCP\n");
+ printf(" IN\n");
+ printf(" IV:");
+ for(int i = 0; i < 16; i++)
+ printf(" %02x", dcp_test.iv[i]);
+ printf("\n");
+ printf(" IV:");
+ for(int i = 0; i < 16; i++)
+ printf(" %02x", dcp_test.data[i]);
+ printf("\n");
+
+ if(!hwstub_aes_otp(&g_hwdev, &dcp_test, sizeof(dcp_test), HWSTUB_AES_OTP_ENCRYPT))
+ {
+ printf(" OUT\n");
+ printf(" IV:");
+ for(int i = 0; i < 16; i++)
+ printf(" %02x", dcp_test.iv[i]);
+ printf("\n");
+ printf(" IV:");
+ for(int i = 0; i < 16; i++)
+ printf(" %02x", dcp_test.data[i]);
+ printf("\n");
+ }
+ else
+ printf("DCP error!\n");
+ }
+#endif
+
+ /** Init lua */
+
+ // create lua state
+ g_lua = luaL_newstate();
+ if(g_lua == NULL)
+ {
+ printf("Cannot create lua state\n");
+ return 1;
+ }
+ // import hwstub
+ if(!my_lua_import_hwstub())
+ printf("Cannot import hwstub description into Lua context\n");
+ // open all standard libraires
+ luaL_openlibs(g_lua);
+ // import socs
+ if(!my_lua_import_soc(socs))
+ printf("Cannot import SoC descriptions into Lua context\n");
+
+ if(luaL_dofile(g_lua, lua_init))
+ printf("error in init: %s\n", lua_tostring(g_lua, -1));
+ lua_pop(g_lua, lua_gettop(g_lua));
+
+ /** start interactive mode */
+ if(!g_quiet)
+ printf("Starting interactive lua session. Type 'help()' to get some help\n");
+
+ // use readline to provide some history and completion
+ rl_bind_key('\t', rl_complete);
+ while(1)
+ {
+ char *input = readline("> ");
+ if(!input)
+ break;
+ add_history(input);
+ // evaluate string
+ if(luaL_dostring(g_lua, input))
+ printf("error: %s\n", lua_tostring(g_lua, -1));
+ // pop everything to start from a clean stack
+ lua_pop(g_lua, lua_gettop(g_lua));
+ free(input);
+ }
+
+ Lerr:
+ // display log if handled
+ if(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
+ {
+ if(!g_quiet)
+ printf("Device log:\n");
+ print_log(&g_hwdev);
+ }
+ hwstub_release(&g_hwdev);
+ return 1;
+}
diff --git a/utils/hwstub/tools/init.lua b/utils/hwstub/tools/init.lua
new file mode 100644
index 0000000000..142c77e20a
--- /dev/null
+++ b/utils/hwstub/tools/init.lua
@@ -0,0 +1,104 @@
+-- init code for hwstub_tools
+
+--
+-- HELP
+--
+HELP = hwstub.help
+
+function HELP:create_topic(name)
+ self[name] = { create_topic = HELP.create_topic, add = HELP.add, get_topic = HELP.get_topic }
+ return self[name]
+end
+
+function HELP:get_topic(name)
+ return self[name]
+end
+
+function HELP:add(text)
+ table.insert(self, text)
+end
+
+do
+ local h = HELP:create_topic("hwstub")
+ h:add("This tool uses a number of well-defined namespaces (tables) to organise its features.")
+ h:add("The hwstub table contains a number of information and functions related to the tool itself.")
+ h:add("Of particular interest are")
+ h:add("* hwstub.host which holds host specific information.")
+ h:add("* hwstub.dev which holds device specific information. See DEV")
+ h:add("* hwstub.help (aka HELP) which holds the help. See HELP.");
+ h:add("* hwstub.soc which holds soc specific information. See HW");
+
+ h = HELP:create_topic("HELP");
+ h:add("This variable redirects to hwstub.help and provides access to the help system.");
+ h:add("You can enhance the help using the following methods on any topic (including HELP itself).");
+ h:add("* t:create_topic(s) to create a new subtopic named s under topic t");
+ h:add("* t:add(s) to add a help line to topic t");
+ h:add("* t:get_topic(s) to get the subtopic s under topic t");
+
+ h = HELP:create_topic("DEV");
+ h:add("This variable redirects to hwstub.dev and provides direct access to the device.");
+ h:add("It contains some information about the device and the following methods.");
+ h:add("* read8/16/32(a) reads a 8/16/32-bit integer at address a");
+ h:add("* write8/16/32(a, v) writes the 8/16/32-bit integer v at address a");
+
+ h = HELP:create_topic("HW");
+ h:add("This variable redirects to the current soc under hwstub.soc and should be changed by calling hwstub:soc:select only.");
+ h:add("The complete register tree can be found under HW in a well organise fashion.");
+ h:add("* HW.dev points to device dev");
+ h:add("* HW.dev[i] points to device devi if there are several copies of the device at different addresses.");
+ h:add("* HW.dev.reg points to the register reg under dev");
+ h:add("* HW.dev.reg[i] points to the register regi if there are several copies.");
+ h:add("* HW.dev.reg.f points to the field f under register reg.");
+ h:add("* HW.dev.reg.f.v gives the value of named value v of field f.");
+ h:add("* All registers can be read using HW.dev.reg.read() and written using HW.dev.reg.write(v).");
+ h:add("* Register with a SCT variant also implement HW.dev.reg.set/clr/tog(v).");
+ h:add("* All register field can be read using HW.dev.reg.f.read() and written using HW.dev.reg.f.write(v).");
+ h:add("* Field writes can either give a integer or a named value to write(v).");
+ h:add("* Register with a SCT variant also implement HW.dev.reg.f.set/clr/tog(v) with the same properties.");
+ h:add("* All devices, registers and fields also have descriptions available such as addresses.");
+end
+
+--
+-- INFO
+--
+
+if not hwstub.options.quiet then
+ print("information")
+ print(" hwstub")
+ print(" version: " .. string.format("%d.%d.%d", hwstub.host.version.major,
+ hwstub.host.version.minor, hwstub.host.version.revision))
+ print(" device")
+ print(" version: " .. string.format("%d.%d.%d", hwstub.dev.version.major,
+ hwstub.dev.version.minor, hwstub.dev.version.revision))
+ print(" layout")
+ print(" on-chip ram")
+ print(" code: " .. string.format("%#x bytes @ %#x",
+ hwstub.dev.layout.ocram.code.size, hwstub.dev.layout.ocram.code.start))
+ print(" stack: " .. string.format("%#x bytes @ %#x",
+ hwstub.dev.layout.ocram.stack.size, hwstub.dev.layout.ocram.stack.start))
+ print(" buffer: " .. string.format("%#x bytes @ %#x",
+ hwstub.dev.layout.ocram.buffer.size, hwstub.dev.layout.ocram.buffer.start))
+ print(" features");
+ print(" log: " .. tostring(hwstub.dev.features.log))
+ print(" mem: " .. tostring(hwstub.dev.features.mem))
+ print(" call: " .. tostring(hwstub.dev.features.call))
+ print(" jump: " .. tostring(hwstub.dev.features.jump))
+ print(" aes_otp: " .. tostring(hwstub.dev.features.aes_otp))
+end
+
+--
+-- SOC
+--
+function hwstub.soc:select(soc)
+ if self[soc] == nil then return false end
+ print("Selecting soc " .. soc .. ". Redirecting HW to hwstub.soc." .. soc)
+ HW = self[soc]
+ return true
+end
+
+--
+-- DEV
+--
+DEV = hwstub.dev
+
+require "lua/load"