summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:02:53 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:25:15 +0200
commitc5357940ab0108b4102442d07825c44d5be0d22f (patch)
treeddfdd9744b1f0ac037fed1c802329cb4542f376b /utils
parent934e1e15af6f2b7bcfdd9dbe8a3a6393ffe5a4a1 (diff)
downloadrockbox-c5357940ab0108b4102442d07825c44d5be0d22f.tar.gz
rockbox-c5357940ab0108b4102442d07825c44d5be0d22f.tar.bz2
rockbox-c5357940ab0108b4102442d07825c44d5be0d22f.zip
hwstub: major improvement in the stub and the tools
Fix the stub in many way to correctly detect the STMP family and act upon that. Drop some unused commands and bump version. Rewrite the tool to allows scripting in lua and load the register description from an XML file using the regtools. Introduce a new tool to load and run code using the hwstub (either binary format or Rockbox additive scramble format). Also switch to an optimise version of the memcpy/move/set functions to correctly handle alignement issue (like writing a full word/half-word when possible for registers which is crucial) Change-Id: Id1d5cfe0b1b47e8b43900d32c5cd6eafae6414f6
Diffstat (limited to 'utils')
-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"