summaryrefslogtreecommitdiff
path: root/utils/hwstub
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/hwstub
parent934e1e15af6f2b7bcfdd9dbe8a3a6393ffe5a4a1 (diff)
downloadrockbox-c5357940ab0108b4102442d07825c44d5be0d22f.tar.gz
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/hwstub')
-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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_PROTOCOL__ 21#ifndef __HWSTUB_PROTOCOL__
22#define __HWEMUL_PROTOCOL__ 22#define __HWSTUB_PROTOCOL__
23 23
24#define HWEMUL_CLASS 0xfe 24#define HWSTUB_CLASS 0xfe
25#define HWEMUL_SUBCLASS 0xac 25#define HWSTUB_SUBCLASS 0xac
26#define HWEMUL_PROTOCOL 0x1d 26#define HWSTUB_PROTOCOL 0x1d
27 27
28#define HWEMUL_VERSION_MAJOR 2 28#define HWSTUB_VERSION_MAJOR 2
29#define HWEMUL_VERSION_MINOR 8 29#define HWSTUB_VERSION_MINOR 9
30#define HWEMUL_VERSION_REV 2 30#define HWSTUB_VERSION_REV 2
31 31
32#define HWEMUL_USB_VID 0xfee1 32#define HWSTUB_USB_VID 0xfee1
33#define HWEMUL_USB_PID 0xdead 33#define HWSTUB_USB_PID 0xdead
34 34
35/** 35/**
36 * Control commands 36 * Control commands
@@ -41,22 +41,22 @@
41 */ 41 */
42 42
43/* list of commands */ 43/* list of commands */
44#define HWEMUL_GET_INFO 0 /* mandatory */ 44#define HWSTUB_GET_INFO 0 /* mandatory */
45#define HWEMUL_GET_LOG 1 /* optional */ 45#define HWSTUB_GET_LOG 1 /* optional */
46#define HWEMUL_RW_MEM 2 /* optional */ 46#define HWSTUB_RW_MEM 2 /* optional */
47#define HWEMUL_CALL 3 /* optional */ 47#define HWSTUB_CALL 3 /* optional */
48#define HWEMUL_JUMP 4 /* optional */ 48#define HWSTUB_JUMP 4 /* optional */
49#define HWEMUL_AES_OTP 5 /* optional */ 49#define HWSTUB_AES_OTP 5 /* optional */
50 50
51/** 51/**
52 * HWEMUL_GET_INFO: get some information about an aspect of the device. 52 * HWSTUB_GET_INFO: get some information about an aspect of the device.
53 * The wIndex field of the SETUP specifies which information to get. */ 53 * The wIndex field of the SETUP specifies which information to get. */
54 54
55/* list of possible information */ 55/* list of possible information */
56#define HWEMUL_INFO_VERSION 0 56#define HWSTUB_INFO_VERSION 0
57#define HWEMUL_INFO_LAYOUT 1 57#define HWSTUB_INFO_LAYOUT 1
58#define HWEMUL_INFO_STMP 2 58#define HWSTUB_INFO_STMP 2
59#define HWEMUL_INFO_FEATURES 3 59#define HWSTUB_INFO_FEATURES 3
60 60
61struct usb_resp_info_version_t 61struct usb_resp_info_version_t
62{ 62{
@@ -86,11 +86,11 @@ struct usb_resp_info_stmp_t
86} __attribute__((packed)); 86} __attribute__((packed));
87 87
88/* list of possible features */ 88/* list of possible features */
89#define HWEMUL_FEATURE_LOG (1 << 0) 89#define HWSTUB_FEATURE_LOG (1 << 0)
90#define HWEMUL_FEATURE_MEM (1 << 1) 90#define HWSTUB_FEATURE_MEM (1 << 1)
91#define HWEMUL_FEATURE_CALL (1 << 2) 91#define HWSTUB_FEATURE_CALL (1 << 2)
92#define HWEMUL_FEATURE_JUMP (1 << 2) 92#define HWSTUB_FEATURE_JUMP (1 << 2)
93#define HWEMUL_FEATURE_AES_OTP (1 << 3) 93#define HWSTUB_FEATURE_AES_OTP (1 << 3)
94 94
95struct usb_resp_info_features_t 95struct usb_resp_info_features_t
96{ 96{
@@ -98,30 +98,32 @@ struct usb_resp_info_features_t
98}; 98};
99 99
100/** 100/**
101 * HWEMUL_GET_LOG: only if has HWEMUL_FEATURE_LOG. 101 * HWSTUB_GET_LOG: only if has HWSTUB_FEATURE_LOG.
102 * The log is returned as part of the control transfer. 102 * The log is returned as part of the control transfer.
103 */ 103 */
104 104
105/** 105/**
106 * HWEMUL_RW_MEM: only if has HWEMUL_FEATURE_MEM. 106 * HWSTUB_RW_MEM: only if has HWSTUB_FEATURE_MEM.
107 * The 32-bit address is split into two parts. 107 * The 32-bit address is split into two parts.
108 * The low 16-bit are stored in wValue and the upper 108 * The low 16-bit are stored in wValue and the upper
109 * 16-bit are stored in wIndex. Depending on the transfer direction, 109 * 16-bit are stored in wIndex. Depending on the transfer direction,
110 * the transfer is either a read or a write. */ 110 * the transfer is either a read or a write.
111 * The read/write on the device are guaranteed to be 16-bit/32-bit when
112 * possible, making it suitable to read/write registers. */
111 113
112/** 114/**
113 * HWEMUL_x: only if has HWEMUL_FEATURE_x where x=CALL or JUMP. 115 * HWSTUB_x: only if has HWSTUB_FEATURE_x where x=CALL or JUMP.
114 * The 32-bit address is split into two parts. 116 * The 32-bit address is split into two parts.
115 * The low 16-bit are stored in wValue and the upper 117 * The low 16-bit are stored in wValue and the upper
116 * 16-bit are stored in wIndex. Depending on the transfer direction, 118 * 16-bit are stored in wIndex. Depending on the transfer direction,
117 * the transfer is either a read or a write. */ 119 * the transfer is either a read or a write. */
118 120
119/** 121/**
120 * HWEMUL_AES_OTP: only if has HWEMUL_FEATURE_AES_OTP. 122 * HWSTUB_AES_OTP: only if has HWSTUB_FEATURE_AES_OTP.
121 * The control transfer contains the data to be en/decrypted and the data 123 * The control transfer contains the data to be en/decrypted and the data
122 * is sent back on the interrupt endpoint. The first 16-bytes of the data 124 * is sent back on the interrupt endpoint. The first 16-bytes of the data
123 * are interpreted as the IV. The output format is the same. 125 * are interpreted as the IV. The output format is the same.
124 * The wValue field contains the parameters of the process. */ 126 * The wValue field contains the parameters of the process. */
125#define HWEMUL_AES_OTP_ENCRYPT (1 << 0) 127#define HWSTUB_AES_OTP_ENCRYPT (1 << 0)
126 128
127#endif /* __HWEMUL_PROTOCOL__ */ 129#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
2AR=ar 2AR=ar
3CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC 3CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC
4LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC 4LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC
5LIB=libhwemul.a 5LIB=libhwstub.a
6REGTOOLS=../../regtools 6SRC=$(wildcard *.c)
7DESC=$(REGTOOLS)/desc
8HWEMULGEN=$(REGTOOLS)/hwemulgen
9HWEMULSOC_PREFIX=hwemul_soc
10SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c
11OBJ=$(SRC:.c=.o) 7OBJ=$(SRC:.c=.o)
12 8
13all: $(LIB) $(EXEC) 9all: $(LIB)
14 10
15$(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h: 11%.o: %.c
16 $(HWEMULGEN) $(DESC)/*.xml $(HWEMULSOC_PREFIX)
17
18%.o: %.c $(HWEMULSOC_PREFIX).h
19 $(CC) $(CFLAGS) -c -o $@ $< 12 $(CC) $(CFLAGS) -c -o $@ $<
20 13
21$(LIB): $(OBJ) 14$(LIB): $(OBJ)
22 $(AR) rcs $@ $^ 15 $(AR) rcs $@ $^
23 16
24clean: 17clean:
25 rm -rf $(OBJ) $(LIB) $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h 18 rm -rf $(OBJ) $(LIB)
26 19
27 20
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 @@
1#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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "hwemul.h" 21#include "hwstub.h"
22#include "hwemul_soc.h"
23 22
24#ifndef MIN 23#ifndef MIN
25#define MIN(a,b) ((a) < (b) ? (a) : (b)) 24#define MIN(a,b) ((a) < (b) ? (a) : (b))
26#endif 25#endif
27 26
28/* requires then ->handle field only */ 27/* requires then ->handle field only */
29int hwemul_probe(struct hwemul_device_t *dev) 28int hwstub_probe(struct hwstub_device_t *dev)
30{ 29{
31 libusb_device *mydev = libusb_get_device(dev->handle); 30 libusb_device *mydev = libusb_get_device(dev->handle);
32 31
@@ -44,9 +43,9 @@ int hwemul_probe(struct hwemul_device_t *dev)
44 const struct libusb_interface_descriptor *interface = 43 const struct libusb_interface_descriptor *interface =
45 &config->interface[intf].altsetting[0]; 44 &config->interface[intf].altsetting[0];
46 if(interface->bNumEndpoints != 3 || 45 if(interface->bNumEndpoints != 3 ||
47 interface->bInterfaceClass != HWEMUL_CLASS || 46 interface->bInterfaceClass != HWSTUB_CLASS ||
48 interface->bInterfaceSubClass != HWEMUL_SUBCLASS || 47 interface->bInterfaceSubClass != HWSTUB_SUBCLASS ||
49 interface->bInterfaceProtocol != HWEMUL_PROTOCOL) 48 interface->bInterfaceProtocol != HWSTUB_PROTOCOL)
50 continue; 49 continue;
51 dev->intf = intf; 50 dev->intf = intf;
52 dev->bulk_in = dev->bulk_out = dev->int_in = -1; 51 dev->bulk_in = dev->bulk_out = dev->int_in = -1;
@@ -73,26 +72,26 @@ int hwemul_probe(struct hwemul_device_t *dev)
73 return libusb_claim_interface(dev->handle, intf); 72 return libusb_claim_interface(dev->handle, intf);
74} 73}
75 74
76int hwemul_release(struct hwemul_device_t *dev) 75int hwstub_release(struct hwstub_device_t *dev)
77{ 76{
78 return libusb_release_interface(dev->handle, dev->intf); 77 return libusb_release_interface(dev->handle, dev->intf);
79} 78}
80 79
81int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz) 80int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz)
82{ 81{
83 return libusb_control_transfer(dev->handle, 82 return libusb_control_transfer(dev->handle,
84 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 83 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
85 HWEMUL_GET_INFO, 0, idx, info, sz, 1000); 84 HWSTUB_GET_INFO, 0, idx, info, sz, 1000);
86} 85}
87 86
88int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz) 87int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
89{ 88{
90 return libusb_control_transfer(dev->handle, 89 return libusb_control_transfer(dev->handle,
91 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 90 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
92 HWEMUL_GET_LOG, 0, 0, buf, sz, 1000); 91 HWSTUB_GET_LOG, 0, 0, buf, sz, 1000);
93} 92}
94 93
95int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) 94int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
96{ 95{
97 size_t tot_sz = 0; 96 size_t tot_sz = 0;
98 while(sz) 97 while(sz)
@@ -101,7 +100,7 @@ int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *bu
101 int ret = libusb_control_transfer(dev->handle, 100 int ret = libusb_control_transfer(dev->handle,
102 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 101 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
103 (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT), 102 (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
104 HWEMUL_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000); 103 HWSTUB_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
105 if(ret != xfer) 104 if(ret != xfer)
106 return ret; 105 return ret;
107 sz -= xfer; 106 sz -= xfer;
@@ -112,23 +111,23 @@ int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *bu
112 return tot_sz; 111 return tot_sz;
113} 112}
114 113
115int hwemul_call(struct hwemul_device_t *dev, uint32_t addr) 114int hwstub_call(struct hwstub_device_t *dev, uint32_t addr)
116{ 115{
117 return libusb_control_transfer(dev->handle, 116 return libusb_control_transfer(dev->handle,
118 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 117 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
119 LIBUSB_ENDPOINT_OUT, HWEMUL_CALL, addr & 0xffff, addr >> 16, NULL, 0, 118 LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0,
120 1000); 119 1000);
121} 120}
122 121
123int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr) 122int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr)
124{ 123{
125 return libusb_control_transfer(dev->handle, 124 return libusb_control_transfer(dev->handle,
126 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 125 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
127 LIBUSB_ENDPOINT_OUT, HWEMUL_JUMP, addr & 0xffff, addr >> 16, NULL, 0, 126 LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
128 1000); 127 1000);
129} 128}
130 129
131const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp) 130const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp)
132{ 131{
133 switch(stmp->chipid) 132 switch(stmp->chipid)
134 { 133 {
@@ -139,7 +138,7 @@ const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
139 } 138 }
140} 139}
141 140
142const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp) 141const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp)
143{ 142{
144 switch(stmp->chipid) 143 switch(stmp->chipid)
145 { 144 {
@@ -159,11 +158,11 @@ const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
159 } 158 }
160} 159}
161 160
162int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param) 161int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param)
163{ 162{
164 int ret = libusb_control_transfer(dev->handle, 163 int ret = libusb_control_transfer(dev->handle,
165 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | 164 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
166 LIBUSB_ENDPOINT_OUT, HWEMUL_AES_OTP, param, 0, buf, sz, 165 LIBUSB_ENDPOINT_OUT, HWSTUB_AES_OTP, param, 0, buf, sz,
167 1000); 166 1000);
168 if(ret <0 || (unsigned)ret != sz) 167 if(ret <0 || (unsigned)ret != sz)
169 return -1; 168 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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL__ 21#ifndef __HWSTUB__
22#define __HWEMUL__ 22#define __HWSTUB__
23 23
24#include <libusb.h> 24#include <libusb.h>
25#include "hwemul_protocol.h" 25#include "hwstub_protocol.h"
26#include "hwemul_soc.h" 26
27#ifdef __cplusplus
28extern "C" {
29#endif
27 30
28/** 31/**
29 * 32 *
@@ -31,7 +34,7 @@
31 * 34 *
32 */ 35 */
33 36
34struct hwemul_device_t 37struct hwstub_device_t
35{ 38{
36 libusb_device_handle *handle; 39 libusb_device_handle *handle;
37 int intf; 40 int intf;
@@ -41,23 +44,27 @@ struct hwemul_device_t
41}; 44};
42 45
43/* Requires then ->handle field only. Returns 0 on success */ 46/* Requires then ->handle field only. Returns 0 on success */
44int hwemul_probe(struct hwemul_device_t *dev); 47int hwstub_probe(struct hwstub_device_t *dev);
45/* Returns 0 on success */ 48/* Returns 0 on success */
46int hwemul_release(struct hwemul_device_t *dev); 49int hwstub_release(struct hwstub_device_t *dev);
47 50
48/* Returns number of bytes filled */ 51/* Returns number of bytes filled */
49int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz); 52int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz);
50/* Returns number of bytes filled */ 53/* Returns number of bytes filled */
51int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz); 54int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
52/* Returns number of bytes written/read or <0 on error */ 55/* Returns number of bytes written/read or <0 on error */
53int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); 56int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
54/* Returns <0 on error */ 57/* Returns <0 on error */
55int hwemul_call(struct hwemul_device_t *dev, uint32_t addr); 58int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);
56int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr); 59int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr);
57/* Returns <0 on error. The size must be a multiple of 16. */ 60/* Returns <0 on error. The size must be a multiple of 16. */
58int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param); 61int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param);
62
63const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp);
64const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp);
59 65
60const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp); 66#ifdef __cplusplus
61const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp); 67} // extern "C"
68#endif
62 69
63#endif /* __HWEMUL__ */ \ No newline at end of file 70#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 @@
1PREFIX?=arm-elf-eabi- 1#
2CC=$(PREFIX)gcc 2# common
3LD=$(PREFIX)gcc 3#
4AS=$(PREFIX)gcc 4CC=arm-elf-eabi-gcc
5OC=$(PREFIX)objcopy 5LD=arm-elf-eabi-gcc
6SBTOOLS=../../sbtools/ 6AS=arm-elf-eabi-gcc
7OC=arm-elf-eabi-objcopy
7CFLAGS=-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 8CFLAGS=-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
8CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700
9ASFLAGS=$(CFLAGS) -D__ASSEMBLER__ 9ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
10ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__
11OCFLAGS= 10OCFLAGS=
12LINKER_FILE=hwemul.lds 11LINKER_FILE=hwstub.lds
13LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map 12TMP_LDS=link.lds
14LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map 13TMP_MAP=hwstub.map
14LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP)
15SRC_C=$(wildcard *.c) 15SRC_C=$(wildcard *.c)
16SRC_S=$(wildcard *.S) 16SRC_S=$(wildcard *.S)
17OBJ_C=$(SRC_C:.c=.o) 17OBJ_C=$(SRC_C:.c=.o)
18OBJ_S=$(SRC_S:.S=.o) 18OBJ_S=$(SRC_S:.S=.o)
19OBJ_C_3700=$(SRC_C:.c=.3700.o)
20OBJ_S_3700=$(SRC_S:.S=.3700.o)
21OBJ=$(OBJ_C) $(OBJ_S) 19OBJ=$(OBJ_C) $(OBJ_S)
22OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700)
23OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ)) 20OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
24OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700))
25DEPS=$(OBJ:.o=.d) 21DEPS=$(OBJ:.o=.d)
26EXEC_ELF=hwemul.elf 22EXEC_ELF=hwstub.elf
27EXEC_SB=hwemul.sb
28EXEC_ELF_3700=hwemul3700.elf
29EXEC_SB_3700=hwemul3700.sb
30 23
24#
25# image production
26#
27TOOLS=../../../tools
28SBTOOLS=../../imxtools/sbtools
29
30# sb (stmp37xx)
31EXEC_SB=hwstub.sb
31ELF2SB=$(SBTOOLS)/elftosb -d 32ELF2SB=$(SBTOOLS)/elftosb -d
32ELF2SB_CMD=-c hwemul.db 33ELF2SB_CMD=-c hwstub.db
33ELF2SB_KEY=-z 34ELF2SB_KEY?=-z
34SBLOADER=$(SBTOOLS)/sbloader
35SBLOADER_CMD=0 $(EXEC_SB)
36SBLOADER_CMD_3700=0 $(EXEC_SB_3700)
37 35
38TOOLS=../../../../tools/ 36# sb1 (stmp36xx)
39SCRAMBLE=$(TOOLS)/scramble 37EXEC_SB1=hwstub.sb1
38ELF2SB1_CMD=-loadjump $(EXEC_ELF)
39ELF2SB1_KEY?=
40ELF2SB1=$(SBTOOLS)/elftosb1 -d
40 41
41EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700) 42EXEC=$(EXEC_ELF) $(EXEC_SB) $(EXEC_SB1)
42 43
43all: $(EXEC) 44all: $(EXEC)
44 45
45# pull in dependency info for *existing* .o files 46# pull in dependency info for *existing* .o files
46-include $(DEPS) 47-include $(DEPS)
47 48
48%.3700.o: %.c
49 $(CC) $(CFLAGS_3700) -c -o $@ $<
50 $(CC) -MM $(CFLAGS_3700) $*.c > $*.d
51 @cp -f $*.d $*.d.tmp
52 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
53 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
54 @rm -f $*.d.tmp
55
56%.o: %.c 49%.o: %.c
57 $(CC) $(CFLAGS) -c -o $@ $< 50 $(CC) $(CFLAGS) -c -o $@ $<
58 $(CC) -MM $(CFLAGS) $*.c > $*.d 51 $(CC) -MM $(CFLAGS) $*.c > $*.d
@@ -61,32 +54,20 @@ all: $(EXEC)
61 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 54 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
62 @rm -f $*.d.tmp 55 @rm -f $*.d.tmp
63 56
64%.3700.o: %.S
65 $(AS) $(ASFLAGS_3700) -c -o $@ $<
66
67%.o: %.S 57%.o: %.S
68 $(AS) $(ASFLAGS) -c -o $@ $< 58 $(AS) $(ASFLAGS) -c -o $@ $<
69 59
70link.lds: $(LINKER_FILE) 60$(TMP_LDS): $(LINKER_FILE)
71 $(CC) -E -x c - < $< | sed '/#/d' > $@ 61 $(CC) -E -x c - < $< | sed '/#/d' > $@
72 62
73$(EXEC_ELF): $(OBJ) link.lds 63$(EXEC_ELF): $(OBJ) $(TMP_LDS)
74 $(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0) 64 $(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
75 65
76$(EXEC_SB): $(EXEC_ELF) 66$(EXEC_SB): $(EXEC_ELF)
77 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@ 67 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
78 68
79$(EXEC_ELF_3700): $(OBJ_3700) link.lds 69$(EXEC_SB1): $(EXEC_ELF)
80 $(LD) $(LDFLAGS_3700) -o $@ $(OBJ_EXCEPT_CRT0_3700) 70 $(ELF2SB1) $(ELF2SB1_CMD) $(ELF2SB1_KEY) -o $@
81
82$(EXEC_SB_3700): $(EXEC_ELF_3700)
83 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
84
85sbload: $(EXEC_SB)
86 $(SBLOADER) $(SBLOADER_CMD)
87
88sbload3700: $(EXEC_SB_3700)
89 $(SBLOADER) $(SBLOADER_CMD_3700)
90 71
91clean: 72clean:
92 rm -rf $(OBJ) $(OBJ_3700) $(DEPS) $(EXEC) *.map 73 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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_CONFIG__ 21#ifndef __HWSTUB_CONFIG__
22#define __HWEMUL_CONFIG__ 22#define __HWSTUB_CONFIG__
23 23
24#define MEMORYSIZE 0 24#define MEMORYSIZE 0
25#define STACK_SIZE 0x1000 25#define STACK_SIZE 0x1000
@@ -30,4 +30,27 @@
30#define DRAM_ORIG 0x40000000 30#define DRAM_ORIG 0x40000000
31#define DRAM_SIZE (MEMORYSIZE * 0x100000) 31#define DRAM_SIZE (MEMORYSIZE * 0x100000)
32 32
33#endif /* __HWEMUL_CONFIG__ */ 33#define CPU_ARM
34#define ARM_ARCH 5
35
36#if defined(CPU_ARM) && defined(__ASSEMBLER__)
37/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */
38.macro ldmpc cond="", order="ia", regs
39#if ARM_ARCH == 4 && defined(USE_THUMB)
40 ldm\cond\order sp!, { \regs, lr }
41 bx\cond lr
42#else
43 ldm\cond\order sp!, { \regs, pc }
44#endif
45.endm
46.macro ldrpc cond=""
47#if ARM_ARCH == 4 && defined(USE_THUMB)
48 ldr\cond lr, [sp], #4
49 bx\cond lr
50#else
51 ldr\cond pc, [sp], #4
52#endif
53.endm
54#endif
55
56#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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_FORMAT__ 21#ifndef __HWSTUB_FORMAT__
22#define __HWEMUL_FORMAT__ 22#define __HWSTUB_FORMAT__
23 23
24#include <stdarg.h> 24#include <stdarg.h>
25 25
26void vuprintf(int (*push)(void *userp, unsigned char data), 26void vuprintf(int (*push)(void *userp, unsigned char data),
27 void *userp, const char *fmt, va_list ap); 27 void *userp, const char *fmt, va_list ap);
28 28
29#endif /* __HWEMUL_FORMAT__ */ 29#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 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21sources 21sources
22{ 22{
23 hwemul = "hwemul.elf"; 23 hwstub = "hwstub.elf";
24} 24}
25 25
26section(0) 26section(0)
27{ 27{
28 load hwemul; 28 load hwstub;
29 jump hwemul(1); 29 jump hwstub(1);
30} 30}
31 31
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
38 { 38 {
39 oc_codestart = .; 39 oc_codestart = .;
40 *(.text*) 40 *(.text*)
41 *(.icode*)
41 *(.data*) 42 *(.data*)
42 *(.rodata*) 43 *(.rodata*)
43 } > OCRAM 44 } > 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 @@
1
2ENTRY(start)
3OUTPUT_FORMAT(elf32-littlearm)
4OUTPUT_ARCH(arm)
5STARTUP(crt0.o)
6
7
8
9MEMORY
10{
11 OCRAM : ORIGIN = 0, LENGTH = 0x8000
12}
13
14SECTIONS
15{
16 .octext :
17 {
18 oc_codestart = .;
19 *(.text*)
20 *(.data*)
21 *(.rodata*)
22 } > OCRAM
23
24 .bss (NOLOAD) :
25 {
26 bss_start = .;
27 *(.bss)
28 bss_end = .;
29 } > OCRAM
30
31 .stack (NOLOAD) :
32 {
33 oc_codeend = .;
34 oc_stackstart = .;
35 . += 0x1000;
36 oc_stackend = .;
37 oc_bufferstart = .;
38 } > OCRAM
39
40 .ocend (0 + 0x8000) (NOLOAD) :
41 {
42 oc_bufferend = .;
43 } > OCRAM
44
45 /DISCARD/ :
46 {
47 *(.eh_frame)
48 }
49}
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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_LOGF__ 21#ifndef __HWSTUB_LOGF__
22#define __HWEMUL_LOGF__ 22#define __HWSTUB_LOGF__
23 23
24#include "stddef.h" 24#include "stddef.h"
25#include <stdarg.h> 25#include <stdarg.h>
@@ -28,4 +28,4 @@ void enable_logf(bool en);
28void logf(const char *fmt, ...); 28void logf(const char *fmt, ...);
29size_t logf_readback(char *buf, size_t max_size); 29size_t logf_readback(char *buf, size_t max_size);
30 30
31#endif /* __HWEMUL_LOGF__ */ 31#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[];
34 34
35/** 35/**
36 * 36 *
37 * Pin control 37 * Global
38 * 38 *
39 */ 39 */
40 40
41#define HW_PINCTRL_BASE 0x80018000 41enum stmp_family_t
42
43#define HW_PINCTRL_CTRL (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x0))
44#define HW_PINCTRL_MUXSEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x100 + (i) * 0x10))
45#define HW_PINCTRL_DRIVE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x200 + (i) * 0x10))
46#ifdef HAVE_STMP3700
47#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x300 + (i) * 0x10))
48#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
49#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
50#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
51#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
52#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
53#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
54#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
55#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
56#else
57#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
58#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
59#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
60#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
61#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
62#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
63#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
64#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
65#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xc00 + (i) * 0x10))
66#endif
67
68#define PINCTRL_FUNCTION_MAIN 0
69#define PINCTRL_FUNCTION_ALT1 1
70#define PINCTRL_FUNCTION_ALT2 2
71#define PINCTRL_FUNCTION_GPIO 3
72
73#define PINCTRL_DRIVE_4mA 0
74#define PINCTRL_DRIVE_8mA 1
75#define PINCTRL_DRIVE_12mA 2
76#define PINCTRL_DRIVE_16mA 3 /* not available on all pins */
77
78typedef void (*pin_irq_cb_t)(int bank, int pin);
79
80static inline void imx233_pinctrl_init(void)
81{ 42{
82 __REG_CLR(HW_PINCTRL_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; 43 UNKNOWN,
83} 44 STMP3600,
84 45 STMP3700,
85static inline void imx233_set_pin_drive_strength(unsigned bank, unsigned pin, unsigned strength) 46 STMP3770,
86{ 47 STMP3780
87 __REG_CLR(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = 3 << (4 * (pin % 8)); 48};
88 __REG_SET(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = strength << (4 * (pin % 8));
89}
90
91static inline void imx233_enable_gpio_output(unsigned bank, unsigned pin, bool enable)
92{
93 if(enable)
94 __REG_SET(HW_PINCTRL_DOE(bank)) = 1 << pin;
95 else
96 __REG_CLR(HW_PINCTRL_DOE(bank)) = 1 << pin;
97}
98
99static inline void imx233_enable_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool enable)
100{
101 if(enable)
102 __REG_SET(HW_PINCTRL_DOE(bank)) = pin_mask;
103 else
104 __REG_CLR(HW_PINCTRL_DOE(bank)) = pin_mask;
105}
106
107static inline void imx233_set_gpio_output(unsigned bank, unsigned pin, bool value)
108{
109 if(value)
110 __REG_SET(HW_PINCTRL_DOUT(bank)) = 1 << pin;
111 else
112 __REG_CLR(HW_PINCTRL_DOUT(bank)) = 1 << pin;
113}
114
115static inline void imx233_set_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool value)
116{
117 if(value)
118 __REG_SET(HW_PINCTRL_DOUT(bank)) = pin_mask;
119 else
120 __REG_CLR(HW_PINCTRL_DOUT(bank)) = pin_mask;
121}
122
123static inline uint32_t imx233_get_gpio_input_mask(unsigned bank, uint32_t pin_mask)
124{
125 return HW_PINCTRL_DIN(bank) & pin_mask;
126}
127
128static inline void imx233_set_pin_function(unsigned bank, unsigned pin, unsigned function)
129{
130 __REG_CLR(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = 3 << (2 * (pin % 16));
131 __REG_SET(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = function << (2 * (pin % 16));
132}
133
134static inline void imx233_enable_pin_pullup(unsigned bank, unsigned pin, bool enable)
135{
136 if(enable)
137 __REG_SET(HW_PINCTRL_PULL(bank)) = 1 << pin;
138 else
139 __REG_CLR(HW_PINCTRL_PULL(bank)) = 1 << pin;
140}
141 49
142static inline void imx233_enable_pin_pullup_mask(unsigned bank, uint32_t pin_msk, bool enable) 50enum stmp_family_t g_stmp_family = UNKNOWN;
143{
144 if(enable)
145 __REG_SET(HW_PINCTRL_PULL(bank)) = pin_msk;
146 else
147 __REG_CLR(HW_PINCTRL_PULL(bank)) = pin_msk;
148}
149 51
150/** 52/**
151 * 53 *
@@ -458,287 +360,38 @@ static void usb_drv_configure_endpoint(int ep_num, int type)
458 360
459/** 361/**
460 * 362 *
461 * Clock control 363 * Clkctrl
462 * 364 *
463 **/ 365 */
464#define __CLK_CLKGATE (1 << 31)
465#define __CLK_BUSY (1 << 29)
466 366
467#define HW_CLKCTRL_BASE 0x80040000 367#define HW_CLKCTRL_BASE 0x80040000
468 368
469#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0)) 369#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
370#define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */
470#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16) 371#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16)
471#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18) 372#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18)
472#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20
473#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20)
474 373
475#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10)) 374#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
375#define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31)
476 376
477#define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20)) 377/* STMP3600 only */
478#define HW_CLKCTRL_CPU__DIV_CPU_BP 0 378#define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
479#define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f 379#define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0
480#define HW_CLKCTRL_CPU__INTERRUPT_WAIT (1 << 12) 380#define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff
481#define HW_CLKCTRL_CPU__DIV_XTAL_BP 16 381#define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30)
482#define HW_CLKCTRL_CPU__DIV_XTAL_BM (0x3ff << 16)
483#define HW_CLKCTRL_CPU__DIV_XTAL_FRAC_EN (1 << 26)
484#define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28)
485
486#define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
487#define HW_CLKCTRL_HBUS__DIV_BP 0
488#define HW_CLKCTRL_HBUS__DIV_BM 0x1f
489#define HW_CLKCTRL_HBUS__DIV_FRAC_EN (1 << 5)
490#define HW_CLKCTRL_HBUS__SLOW_DIV_BP 16
491#define HW_CLKCTRL_HBUS__SLOW_DIV_BM (0x7 << 16)
492#define HW_CLKCTRL_HBUS__AUTO_SLOW_MODE (1 << 20)
493
494#define HW_CLKCTRL_XBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
495#define HW_CLKCTRL_XBUS__DIV_BP 0
496#define HW_CLKCTRL_XBUS__DIV_BM 0x3ff
497#define HW_CLKCTRL_XBUS__BUSY (1 << 31)
498
499#define HW_CLKCTRL_XTAL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x50))
500#define HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE (1 << 26)
501#define HW_CLKCTRL_XTAL__DRI_CLK24M_GATE (1 << 28)
502#define HW_CLKCTRL_XTAL__PWM_CLK24M_GATE (1 << 29)
503#define HW_CLKCTRL_XTAL__FILT_CLK24M_GATE (1 << 30)
504
505#define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60))
506#define HW_CLKCTRL_PIX__DIV_BP 0
507#define HW_CLKCTRL_PIX__DIV_BM 0xfff
508
509#define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
510#define HW_CLKCTRL_SSP__DIV_BP 0
511#define HW_CLKCTRL_SSP__DIV_BM 0x1ff
512
513#define HW_CLKCTRL_EMI (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xa0))
514#define HW_CLKCTRL_EMI__DIV_EMI_BP 0
515#define HW_CLKCTRL_EMI__DIV_EMI_BM 0x3f
516#define HW_CLKCTRL_EMI__DIV_XTAL_BP 8
517#define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8)
518#define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28)
519#define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30)
520#define HW_CLKCTRL_EMI__CLKGATE (1 << 31)
521
522#ifdef HAVE_STMP3770
523#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xe0))
524#else
525#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110))
526#endif
527#define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1)
528#define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5)
529#define HW_CLKCTRL_CLKSEQ__BYPASS_EMI (1 << 6)
530#define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7)
531
532#ifdef HAVE_STMP3770
533#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xd0))
534#else
535#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0))
536#endif
537#define HW_CLKCTRL_FRAC_CPU (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf0))
538#define HW_CLKCTRL_FRAC_EMI (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf1))
539#define HW_CLKCTRL_FRAC_PIX (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf2))
540#define HW_CLKCTRL_FRAC_IO (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf3))
541#define HW_CLKCTRL_FRAC_XX__XXDIV_BM 0x3f
542#define HW_CLKCTRL_FRAC_XX__XX_STABLE (1 << 6)
543#define HW_CLKCTRL_FRAC_XX__CLKGATEXX (1 << 7)
544
545#define HW_CLKCTRL_RESET (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x120))
546#define HW_CLKCTRL_RESET_CHIP 0x2
547#define HW_CLKCTRL_RESET_DIG 0x1
548
549/**
550 *
551 * DMA
552 *
553 */
554
555/********
556 * APHB *
557 ********/
558
559#define HW_APBH_BASE 0x80004000
560
561/* APHB channels */
562#define HW_APBH_SSP(ssp) ssp
563
564#define HW_APBH_CTRL0 (*(volatile uint32_t *)(HW_APBH_BASE + 0x0))
565#define HW_APBH_CTRL0__FREEZE_CHANNEL(i) (1 << (i))
566#define HW_APBH_CTRL0__CLKGATE_CHANNEL(i) (1 << ((i) + 8))
567#define HW_APBH_CTRL0__RESET_CHANNEL(i) (1 << ((i) + 16))
568#define HW_APBH_CTRL0__APB_BURST4_EN (1 << 28)
569#define HW_APBH_CTRL0__APB_BURST8_EN (1 << 29)
570
571#define HW_APBH_CTRL1 (*(volatile uint32_t *)(HW_APBH_BASE + 0x10))
572#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
573#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
574
575#define HW_APBH_CTRL2 (*(volatile uint32_t *)(HW_APBH_BASE + 0x20))
576#define HW_APBH_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
577#define HW_APBH_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
578
579#define HW_APBH_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x40 + 0x70 * (i)))
580
581#define HW_APBH_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x50 + 0x70 * (i)))
582
583#define HW_APBH_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x60 + 0x70 * (i)))
584
585#define HW_APBH_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x70 + 0x70 * (i)))
586
587#define HW_APBH_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x80 + 0x70 * (i)))
588
589#define HW_APBH_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x90 + 0x70 * (i)))
590
591#define HW_APBH_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0xa0 + 0x70 * (i)))
592#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BP 0
593#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BM 0xffff
594#define HW_APBH_CHx_DEBUG2__APB_BYTES_BP 16
595#define HW_APBH_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
596
597/********
598 * APHX *
599 ********/
600
601/* APHX channels */
602#define HW_APBX_AUDIO_ADC 0
603#define HW_APBX_AUDIO_DAC 1
604#define HW_APBX_I2C 3
605
606#define HW_APBX_BASE 0x80024000
607
608#define HW_APBX_CTRL0 (*(volatile uint32_t *)(HW_APBX_BASE + 0x0))
609
610#define HW_APBX_CTRL1 (*(volatile uint32_t *)(HW_APBX_BASE + 0x10))
611#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
612#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
613
614#define HW_APBX_CTRL2 (*(volatile uint32_t *)(HW_APBX_BASE + 0x20))
615#define HW_APBX_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
616#define HW_APBX_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
617 382
618#define HW_APBX_CHANNEL_CTRL (*(volatile uint32_t *)(HW_APBX_BASE + 0x30)) 383/* STMP3600 */
619#define HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(i) (1 << (i)) 384#define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
620#define HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(i) (1 << ((i) + 16))
621 385
622#define HW_APBX_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x100 + (i) * 0x70)) 386/* STMP3600 only */
387#define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
388#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0
389#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff
623 390
624#define HW_APBX_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x110 + (i) * 0x70)) 391/* STMP3600 only */
625 392#define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
626#define HW_APBX_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x120 + (i) * 0x70)) 393#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30)
627 394#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31)
628#define HW_APBX_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x130 + (i) * 0x70))
629
630#define HW_APBX_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x140 + (i) * 0x70))
631
632#define HW_APBX_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x150 + (i) * 0x70))
633
634#define HW_APBX_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x160 + (i) * 0x70))
635#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BP 0
636#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BM 0xffff
637#define HW_APBX_CHx_DEBUG2__APB_BYTES_BP 16
638#define HW_APBX_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
639
640/**********
641 * COMMON *
642 **********/
643
644struct apb_dma_command_t
645{
646 struct apb_dma_command_t *next;
647 uint32_t cmd;
648 void *buffer;
649 /* PIO words follow */
650};
651
652#define APBH_DMA_CHANNEL(i) i
653#define APBX_DMA_CHANNEL(i) ((i) | 0x10)
654#define APB_IS_APBX_CHANNEL(x) ((x) & 0x10)
655#define APB_GET_DMA_CHANNEL(x) ((x) & 0xf)
656
657#define APB_SSP(ssp) APBH_DMA_CHANNEL(HW_APBH_SSP(ssp))
658#define APB_AUDIO_ADC APBX_DMA_CHANNEL(HW_APBX_AUDIO_ADC)
659#define APB_AUDIO_DAC APBX_DMA_CHANNEL(HW_APBX_AUDIO_DAC)
660#define APB_I2C APBX_DMA_CHANNEL(HW_APBX_I2C)
661
662#define HW_APB_CHx_CMD__COMMAND_BM 0x3
663#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0
664#define HW_APB_CHx_CMD__COMMAND__WRITE 1
665#define HW_APB_CHx_CMD__COMMAND__READ 2
666#define HW_APB_CHx_CMD__COMMAND__SENSE 3
667#define HW_APB_CHx_CMD__CHAIN (1 << 2)
668#define HW_APB_CHx_CMD__IRQONCMPLT (1 << 3)
669/* those two are only available on APHB */
670#define HW_APBH_CHx_CMD__NANDLOCK (1 << 4)
671#define HW_APBH_CHx_CMD__NANDWAIT4READY (1 << 5)
672#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6)
673#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7)
674/* An errata advise not to use it */
675//#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
676#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000
677#define HW_APB_CHx_CMD__CMDWORDS_BP 12
678#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000
679#define HW_APB_CHx_CMD__XFER_COUNT_BP 16
680/* For software use */
681#define HW_APB_CHx_CMD__UNUSED_BP 8
682#define HW_APB_CHx_CMD__UNUSED_BM (0xf << 8)
683#define HW_APB_CHx_CMD__UNUSED_MAGIC (0xa << 8)
684
685#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000
686#define HW_APB_CHx_SEMA__PHORE_BP 16
687
688/* A single descriptor cannot transfer more than 2^16 bytes */
689#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16)
690
691static void imx233_dma_init(void)
692{
693 __REG_CLR(HW_APBH_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
694 __REG_CLR(HW_APBX_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
695}
696
697static void imx233_dma_reset_channel(unsigned chan)
698{
699 volatile uint32_t *ptr;
700 uint32_t bm;
701 if(APB_IS_APBX_CHANNEL(chan))
702 {
703 ptr = &HW_APBX_CHANNEL_CTRL;
704 bm = HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
705 }
706 else
707 {
708 ptr = &HW_APBH_CTRL0;
709 bm = HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
710 }
711 __REG_SET(*ptr) = bm;
712 /* wait for end of reset */
713 while(*ptr & bm)
714 ;
715}
716
717static void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
718{
719 if(APB_IS_APBX_CHANNEL(chan))
720 {
721 HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
722 HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
723 }
724 else
725 {
726 HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
727 HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
728 }
729}
730
731static void imx233_dma_wait_completion(unsigned chan)
732{
733 volatile uint32_t *sema;
734 if(APB_IS_APBX_CHANNEL(chan))
735 sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
736 else
737 sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
738
739 while(*sema & HW_APB_CHx_SEMA__PHORE_BM)
740 ;
741}
742 395
743/** 396/**
744 * 397 *
@@ -751,8 +404,6 @@ static void imx233_dma_wait_completion(unsigned chan)
751#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0)) 404#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
752#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2) 405#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
753 406
754#define HW_DIGCTL_HCLKCOUNT (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x20))
755
756#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) 407#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
757 408
758#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310)) 409#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
@@ -786,7 +437,6 @@ static void udelay(unsigned us)
786/* USB Phy */ 437/* USB Phy */
787#define HW_USBPHY_BASE 0x8007C000 438#define HW_USBPHY_BASE 0x8007C000
788#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0)) 439#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
789#define HW_USBPHY_PWD__ALL (7 << 10 | 0xf << 17)
790 440
791#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30)) 441#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
792 442
@@ -852,17 +502,9 @@ struct dcp_packet_t
852 * 502 *
853 */ 503 */
854 504
855void memcpy(uint8_t *dst, const uint8_t *src, uint32_t length) 505void memcpy(void *dest, const void *src, size_t n);
856{ 506void memmove(void *dest, const void *src, size_t n);
857 for(uint32_t i = 0; i < length; i++) 507void memset(void *dst, int value, size_t n);
858 dst[i] = src[i];
859}
860
861void memset(uint8_t *dst, uint8_t fill, uint32_t length)
862{
863 for(uint32_t i = 0; i < length; i++)
864 dst[i] = fill;
865}
866 508
867/** 509/**
868 * 510 *
@@ -880,9 +522,9 @@ static struct usb_device_descriptor __attribute__((aligned(2)))
880 .bDeviceSubClass = 0, 522 .bDeviceSubClass = 0,
881 .bDeviceProtocol = 0, 523 .bDeviceProtocol = 0,
882 .bMaxPacketSize0 = 64, 524 .bMaxPacketSize0 = 64,
883 .idVendor = HWEMUL_USB_VID, 525 .idVendor = HWSTUB_USB_VID,
884 .idProduct = HWEMUL_USB_PID, 526 .idProduct = HWSTUB_USB_PID,
885 .bcdDevice = HWEMUL_VERSION_MAJOR << 8 | HWEMUL_VERSION_MINOR, 527 .bcdDevice = HWSTUB_VERSION_MAJOR << 8 | HWSTUB_VERSION_MINOR,
886 .iManufacturer = 1, 528 .iManufacturer = 1,
887 .iProduct = 2, 529 .iProduct = 2,
888 .iSerialNumber = 3, 530 .iSerialNumber = 3,
@@ -913,9 +555,9 @@ static struct usb_interface_descriptor __attribute__((aligned(2)))
913 .bInterfaceNumber = 0, 555 .bInterfaceNumber = 0,
914 .bAlternateSetting = 0, 556 .bAlternateSetting = 0,
915 .bNumEndpoints = 3, 557 .bNumEndpoints = 3,
916 .bInterfaceClass = HWEMUL_CLASS, 558 .bInterfaceClass = HWSTUB_CLASS,
917 .bInterfaceSubClass = HWEMUL_SUBCLASS, 559 .bInterfaceSubClass = HWSTUB_SUBCLASS,
918 .bInterfaceProtocol = HWEMUL_PROTOCOL, 560 .bInterfaceProtocol = HWSTUB_PROTOCOL,
919 .iInterface = 4 561 .iInterface = 4
920}; 562};
921 563
@@ -966,9 +608,9 @@ static struct usb_string_descriptor __attribute__((aligned(2)))
966 28, 608 28,
967 USB_DT_STRING, 609 USB_DT_STRING,
968 {'A', 'c', 'i', 'd', ' ', 610 {'A', 'c', 'i', 'd', ' ',
969 '0' + (HWEMUL_VERSION_MAJOR >> 4), '0' + (HWEMUL_VERSION_MAJOR & 0xf), '.', 611 '0' + (HWSTUB_VERSION_MAJOR >> 4), '0' + (HWSTUB_VERSION_MAJOR & 0xf), '.',
970 '0' + (HWEMUL_VERSION_MINOR >> 4), '0' + (HWEMUL_VERSION_MINOR & 0xf), '.', 612 '0' + (HWSTUB_VERSION_MINOR >> 4), '0' + (HWSTUB_VERSION_MINOR & 0xf), '.',
971 '0' + (HWEMUL_VERSION_REV >> 4), '0' + (HWEMUL_VERSION_REV & 0xf) } 613 '0' + (HWSTUB_VERSION_REV >> 4), '0' + (HWSTUB_VERSION_REV & 0xf) }
972}; 614};
973 615
974/* this is stringid #0: languages supported */ 616/* this is stringid #0: languages supported */
@@ -1138,9 +780,9 @@ static void handle_std_req(struct usb_ctrlrequest *req)
1138 780
1139struct usb_resp_info_version_t g_version = 781struct usb_resp_info_version_t g_version =
1140{ 782{
1141 .major = HWEMUL_VERSION_MAJOR, 783 .major = HWSTUB_VERSION_MAJOR,
1142 .minor = HWEMUL_VERSION_MINOR, 784 .minor = HWSTUB_VERSION_MINOR,
1143 .revision = HWEMUL_VERSION_REV 785 .revision = HWSTUB_VERSION_REV
1144}; 786};
1145 787
1146struct usb_resp_info_layout_t g_layout; 788struct usb_resp_info_layout_t g_layout;
@@ -1149,8 +791,8 @@ struct usb_resp_info_stmp_t g_stmp;
1149 791
1150struct usb_resp_info_features_t g_features = 792struct usb_resp_info_features_t g_features =
1151{ 793{
1152 .feature_mask = HWEMUL_FEATURE_LOG | HWEMUL_FEATURE_MEM | 794 .feature_mask = HWSTUB_FEATURE_LOG | HWSTUB_FEATURE_MEM |
1153 HWEMUL_FEATURE_CALL | HWEMUL_FEATURE_JUMP | HWEMUL_FEATURE_AES_OTP 795 HWSTUB_FEATURE_CALL | HWSTUB_FEATURE_JUMP | HWSTUB_FEATURE_AES_OTP
1154}; 796};
1155 797
1156static void fill_layout_info(void) 798static void fill_layout_info(void)
@@ -1177,21 +819,21 @@ static void handle_get_info(struct usb_ctrlrequest *req)
1177 int size = 0; 819 int size = 0;
1178 switch(req->wIndex) 820 switch(req->wIndex)
1179 { 821 {
1180 case HWEMUL_INFO_VERSION: 822 case HWSTUB_INFO_VERSION:
1181 ptr = &g_version; 823 ptr = &g_version;
1182 size = sizeof(g_version); 824 size = sizeof(g_version);
1183 break; 825 break;
1184 case HWEMUL_INFO_LAYOUT: 826 case HWSTUB_INFO_LAYOUT:
1185 fill_layout_info(); 827 fill_layout_info();
1186 ptr = &g_layout; 828 ptr = &g_layout;
1187 size = sizeof(g_layout); 829 size = sizeof(g_layout);
1188 break; 830 break;
1189 case HWEMUL_INFO_STMP: 831 case HWSTUB_INFO_STMP:
1190 fill_stmp_info(); 832 fill_stmp_info();
1191 ptr = &g_stmp; 833 ptr = &g_stmp;
1192 size = sizeof(g_stmp); 834 size = sizeof(g_stmp);
1193 break; 835 break;
1194 case HWEMUL_INFO_FEATURES: 836 case HWSTUB_INFO_FEATURES:
1195 ptr = &g_features; 837 ptr = &g_features;
1196 size = sizeof(g_features); 838 size = sizeof(g_features);
1197 break; 839 break;
@@ -1249,17 +891,22 @@ static void handle_call_jump(struct usb_ctrlrequest *req)
1249{ 891{
1250 uint32_t addr = req->wValue | req->wIndex << 16; 892 uint32_t addr = req->wValue | req->wIndex << 16;
1251 893
1252 if(req->bRequest == HWEMUL_CALL) 894 if(req->bRequest == HWSTUB_CALL)
1253 ((void (*)(void))addr)(); 895 ((void (*)(void))addr)();
1254 else 896 else
897 {
898 /* disconnect to make sure usb/dma won't interfere */
899 REG_USBCMD &= ~USBCMD_RUN;
900 REG_USBCMD |= USBCMD_CTRL_RESET;
1255 asm volatile("bx %0\n" : : "r" (addr) : "memory"); 901 asm volatile("bx %0\n" : : "r" (addr) : "memory");
902 }
1256} 903}
1257 904
1258static void do_aes_otp(void *buffer, unsigned length, unsigned params) 905static void do_aes_otp(void *buffer, unsigned length, unsigned params)
1259{ 906{
1260 static struct dcp_packet_t dcp_packet; 907 static struct dcp_packet_t dcp_packet;
1261 908
1262 bool encrypt = !!(params & HWEMUL_AES_OTP_ENCRYPT); 909 bool encrypt = !!(params & HWSTUB_AES_OTP_ENCRYPT);
1263 /* reset DCP */ 910 /* reset DCP */
1264 __REG_SET(HW_DCP_CTRL) = 0x80000000; 911 __REG_SET(HW_DCP_CTRL) = 0x80000000;
1265 /* clear clock gate */ 912 /* clear clock gate */
@@ -1307,20 +954,20 @@ static void handle_class_dev_req(struct usb_ctrlrequest *req)
1307{ 954{
1308 switch(req->bRequest) 955 switch(req->bRequest)
1309 { 956 {
1310 case HWEMUL_GET_INFO: 957 case HWSTUB_GET_INFO:
1311 handle_get_info(req); 958 handle_get_info(req);
1312 break; 959 break;
1313 case HWEMUL_GET_LOG: 960 case HWSTUB_GET_LOG:
1314 handle_get_log(req); 961 handle_get_log(req);
1315 break; 962 break;
1316 case HWEMUL_RW_MEM: 963 case HWSTUB_RW_MEM:
1317 handle_rw_mem(req); 964 handle_rw_mem(req);
1318 break; 965 break;
1319 case HWEMUL_CALL: 966 case HWSTUB_CALL:
1320 case HWEMUL_JUMP: 967 case HWSTUB_JUMP:
1321 handle_call_jump(req); 968 handle_call_jump(req);
1322 break; 969 break;
1323 case HWEMUL_AES_OTP: 970 case HWSTUB_AES_OTP:
1324 handle_aes_otp(req); 971 handle_aes_otp(req);
1325 break; 972 break;
1326 default: 973 default:
@@ -1348,19 +995,68 @@ static void handle_class_req(struct usb_ctrlrequest *req)
1348void main(uint32_t arg) 995void main(uint32_t arg)
1349{ 996{
1350 usb_buffer_size = oc_buffersize; 997 usb_buffer_size = oc_buffersize;
1351 998
1352 logf("hwemul %d.%d.%d\n", HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, 999 logf("hwstub %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR,
1353 HWEMUL_VERSION_REV); 1000 HWSTUB_VERSION_REV);
1354 logf("argument: 0x%08x\n", arg); 1001 logf("argument: 0x%08x\n", arg);
1355 1002
1003 /* detect family */
1004 uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
1005 if(product_code >= 0x3600 && product_code < 0x3700)
1006 {
1007 logf("identified STMP3600 family\n");
1008 g_stmp_family = STMP3600;
1009 }
1010 else if(product_code == 0x3700)
1011 {
1012 logf("identified STMP3700 family\n");
1013 g_stmp_family = STMP3700;
1014 }
1015 else if(product_code == 0x37b0)
1016 {
1017 logf("identified STMP3770 family\n");
1018 g_stmp_family = STMP3770;
1019 }
1020 else if(product_code == 0x3780)
1021 {
1022 logf("identified STMP3780 family\n");
1023 g_stmp_family = STMP3780;
1024 }
1025 else
1026 logf("cannot identify family: 0x%x\n", product_code);
1027
1356 /* we don't know if USB was connected or not. In USB recovery mode it will 1028 /* we don't know if USB was connected or not. In USB recovery mode it will
1357 * but in other cases it might not be. In doubt, disconnect */ 1029 * but in other cases it might not be. In doubt, disconnect */
1358 REG_USBCMD &= ~USBCMD_RUN; 1030 REG_USBCMD &= ~USBCMD_RUN;
1031 if(g_stmp_family == STMP3600)
1032 {
1033 /* CPU clock is always derived from PLL, if we switch to PLL, cpu will
1034 * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed
1035 * (1.2MHz) for a safe transition */
1036 HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400;
1037 /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the
1038 * switch so lower XBUS too */
1039 HW_CLKCTRL_XBUSCLKCTRL = 20;
1040 /* Power PLL */
1041 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
1042 HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480;
1043 /* Wait lock */
1044 while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK));
1045 /* Switch to PLL source */
1046 __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS;
1047 /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */
1048 HW_CLKCTRL_CPUCLKCTRL = 7;
1049 HW_CLKCTRL_HBUSCLKCTRL = 7;
1050 HW_CLKCTRL_XBUSCLKCTRL = 1;
1051 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE;
1052 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE;
1053 }
1054 else
1055 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
1359 /* enable USB PHY PLL */ 1056 /* enable USB PHY PLL */
1360 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; 1057 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
1361 /* power up USB PHY */ 1058 /* power up USB PHY */
1362 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; 1059 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
1363 //__REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
1364 HW_USBPHY_PWD = 0; 1060 HW_USBPHY_PWD = 0;
1365 /* enable USB controller */ 1061 /* enable USB controller */
1366 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; 1062 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
@@ -1382,7 +1078,7 @@ void main(uint32_t arg)
1382 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0; 1078 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1383 /* run! */ 1079 /* run! */
1384 REG_USBCMD |= USBCMD_RUN; 1080 REG_USBCMD |= USBCMD_RUN;
1385 1081
1386 while(1) 1082 while(1)
1387 { 1083 {
1388 /* wait for setup */ 1084 /* 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Free Software Foundation, Inc.
11 * This file was originally part of the GNU C Library
12 * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)
13 * Adapted for Rockbox by Daniel Ankers
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include "config.h"
26
27/*
28 * Endian independent macros for shifting bytes within registers.
29 */
30#ifndef __ARMEB__
31#define pull lsr
32#define push lsl
33#else
34#define pull lsl
35#define push lsr
36#endif
37
38/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
39
40 .section .icode,"ax",%progbits
41
42 .align 2
43 .global memcpy
44 .type memcpy,%function
45
46memcpy:
47 stmfd sp!, {r0, r4, lr}
48
49 subs r2, r2, #4
50 blt 8f
51 ands ip, r0, #3
52 bne 9f
53 ands ip, r1, #3
54 bne 10f
55
561: subs r2, r2, #(28)
57 stmfd sp!, {r5 - r8}
58 blt 5f
59
602:
613:
624: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
63 subs r2, r2, #32
64 stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
65 bge 3b
66
675: ands ip, r2, #28
68 rsb ip, ip, #32
69 addne pc, pc, ip @ C is always clear here
70 b 7f
716: nop
72 ldr r3, [r1], #4
73 ldr r4, [r1], #4
74 ldr r5, [r1], #4
75 ldr r6, [r1], #4
76 ldr r7, [r1], #4
77 ldr r8, [r1], #4
78 ldr lr, [r1], #4
79
80 add pc, pc, ip
81 nop
82 nop
83 str r3, [r0], #4
84 str r4, [r0], #4
85 str r5, [r0], #4
86 str r6, [r0], #4
87 str r7, [r0], #4
88 str r8, [r0], #4
89 str lr, [r0], #4
90
917: ldmfd sp!, {r5 - r8}
92
938: movs r2, r2, lsl #31
94 ldrneb r3, [r1], #1
95 ldrcsb r4, [r1], #1
96 ldrcsb ip, [r1]
97 strneb r3, [r0], #1
98 strcsb r4, [r0], #1
99 strcsb ip, [r0]
100
101 ldmpc regs="r0, r4"
102
1039: rsb ip, ip, #4
104 cmp ip, #2
105 ldrgtb r3, [r1], #1
106 ldrgeb r4, [r1], #1
107 ldrb lr, [r1], #1
108 strgtb r3, [r0], #1
109 strgeb r4, [r0], #1
110 subs r2, r2, ip
111 strb lr, [r0], #1
112 blt 8b
113 ands ip, r1, #3
114 beq 1b
115
11610: bic r1, r1, #3
117 cmp ip, #2
118 ldr lr, [r1], #4
119 beq 17f
120 bgt 18f
121
122
123 .macro forward_copy_shift pull push
124
125 subs r2, r2, #28
126 blt 14f
127
12811: stmfd sp!, {r5 - r9}
129
13012:
13113: ldmia r1!, {r4, r5, r6, r7}
132 mov r3, lr, pull #\pull
133 subs r2, r2, #32
134 ldmia r1!, {r8, r9, ip, lr}
135 orr r3, r3, r4, push #\push
136 mov r4, r4, pull #\pull
137 orr r4, r4, r5, push #\push
138 mov r5, r5, pull #\pull
139 orr r5, r5, r6, push #\push
140 mov r6, r6, pull #\pull
141 orr r6, r6, r7, push #\push
142 mov r7, r7, pull #\pull
143 orr r7, r7, r8, push #\push
144 mov r8, r8, pull #\pull
145 orr r8, r8, r9, push #\push
146 mov r9, r9, pull #\pull
147 orr r9, r9, ip, push #\push
148 mov ip, ip, pull #\pull
149 orr ip, ip, lr, push #\push
150 stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
151 bge 12b
152
153 ldmfd sp!, {r5 - r9}
154
15514: ands ip, r2, #28
156 beq 16f
157
15815: mov r3, lr, pull #\pull
159 ldr lr, [r1], #4
160 subs ip, ip, #4
161 orr r3, r3, lr, push #\push
162 str r3, [r0], #4
163 bgt 15b
164
16516: sub r1, r1, #(\push / 8)
166 b 8b
167
168 .endm
169
170
171 forward_copy_shift pull=8 push=24
172
17317: forward_copy_shift pull=16 push=16
174
17518: forward_copy_shift pull=24 push=8
176
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Free Software Foundation, Inc.
11 * This file was originally part of the GNU C Library
12 * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)
13 * Adapted for Rockbox by Daniel Ankers
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include "config.h"
26
27/*
28 * Endian independent macros for shifting bytes within registers.
29 */
30#ifndef __ARMEB__
31#define pull lsr
32#define push lsl
33#else
34#define pull lsl
35#define push lsr
36#endif
37
38 .text
39
40/*
41 * Prototype: void *memmove(void *dest, const void *src, size_t n);
42 *
43 * Note:
44 *
45 * If the memory regions don't overlap, we simply branch to memcpy which is
46 * normally a bit faster. Otherwise the copy is done going downwards.
47 */
48
49 .section .icode,"ax",%progbits
50
51 .align 2
52 .global memmove
53 .type memmove,%function
54
55memmove:
56
57 subs ip, r0, r1
58 cmphi r2, ip
59 bls memcpy
60
61 stmfd sp!, {r0, r4, lr}
62 add r1, r1, r2
63 add r0, r0, r2
64 subs r2, r2, #4
65 blt 8f
66 ands ip, r0, #3
67 bne 9f
68 ands ip, r1, #3
69 bne 10f
70
711: subs r2, r2, #(28)
72 stmfd sp!, {r5 - r8}
73 blt 5f
74
752:
763:
774: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
78 subs r2, r2, #32
79 stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
80 bge 3b
81
825: ands ip, r2, #28
83 rsb ip, ip, #32
84 addne pc, pc, ip @ C is always clear here
85 b 7f
866: nop
87 ldr r3, [r1, #-4]!
88 ldr r4, [r1, #-4]!
89 ldr r5, [r1, #-4]!
90 ldr r6, [r1, #-4]!
91 ldr r7, [r1, #-4]!
92 ldr r8, [r1, #-4]!
93 ldr lr, [r1, #-4]!
94
95 add pc, pc, ip
96 nop
97 nop
98 str r3, [r0, #-4]!
99 str r4, [r0, #-4]!
100 str r5, [r0, #-4]!
101 str r6, [r0, #-4]!
102 str r7, [r0, #-4]!
103 str r8, [r0, #-4]!
104 str lr, [r0, #-4]!
105
1067: ldmfd sp!, {r5 - r8}
107
1088: movs r2, r2, lsl #31
109 ldrneb r3, [r1, #-1]!
110 ldrcsb r4, [r1, #-1]!
111 ldrcsb ip, [r1, #-1]
112 strneb r3, [r0, #-1]!
113 strcsb r4, [r0, #-1]!
114 strcsb ip, [r0, #-1]
115 ldmpc regs="r0, r4"
116
1179: cmp ip, #2
118 ldrgtb r3, [r1, #-1]!
119 ldrgeb r4, [r1, #-1]!
120 ldrb lr, [r1, #-1]!
121 strgtb r3, [r0, #-1]!
122 strgeb r4, [r0, #-1]!
123 subs r2, r2, ip
124 strb lr, [r0, #-1]!
125 blt 8b
126 ands ip, r1, #3
127 beq 1b
128
12910: bic r1, r1, #3
130 cmp ip, #2
131 ldr r3, [r1, #0]
132 beq 17f
133 blt 18f
134
135
136 .macro backward_copy_shift push pull
137
138 subs r2, r2, #28
139 blt 14f
140
14111: stmfd sp!, {r5 - r9}
142
14312:
14413: ldmdb r1!, {r7, r8, r9, ip}
145 mov lr, r3, push #\push
146 subs r2, r2, #32
147 ldmdb r1!, {r3, r4, r5, r6}
148 orr lr, lr, ip, pull #\pull
149 mov ip, ip, push #\push
150 orr ip, ip, r9, pull #\pull
151 mov r9, r9, push #\push
152 orr r9, r9, r8, pull #\pull
153 mov r8, r8, push #\push
154 orr r8, r8, r7, pull #\pull
155 mov r7, r7, push #\push
156 orr r7, r7, r6, pull #\pull
157 mov r6, r6, push #\push
158 orr r6, r6, r5, pull #\pull
159 mov r5, r5, push #\push
160 orr r5, r5, r4, pull #\pull
161 mov r4, r4, push #\push
162 orr r4, r4, r3, pull #\pull
163 stmdb r0!, {r4 - r9, ip, lr}
164 bge 12b
165
166 ldmfd sp!, {r5 - r9}
167
16814: ands ip, r2, #28
169 beq 16f
170
17115: mov lr, r3, push #\push
172 ldr r3, [r1, #-4]!
173 subs ip, ip, #4
174 orr lr, lr, r3, pull #\pull
175 str lr, [r0, #-4]!
176 bgt 15b
177
17816: add r1, r1, #(\pull / 8)
179 b 8b
180
181 .endm
182
183
184 backward_copy_shift push=8 pull=24
185
18617: backward_copy_shift push=16 pull=16
187
18818: backward_copy_shift push=24 pull=8
189
190
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Thom Johansen
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23 .section .icode,"ax",%progbits
24
25 .align 2
26
27/* The following code is based on code found in Linux kernel version 2.6.15.3
28 * linux/arch/arm/lib/memset.S
29 *
30 * Copyright (C) 1995-2000 Russell King
31 */
32
33/* This code will align a pointer for memset, if needed */
341: cmp r2, #4 @ 1 do we have enough
35 blt 5f @ 1 bytes to align with?
36 cmp r3, #2 @ 1
37 strgtb r1, [r0, #-1]! @ 1
38 strgeb r1, [r0, #-1]! @ 1
39 strb r1, [r0, #-1]! @ 1
40 sub r2, r2, r3 @ 1 r2 = r2 - r3
41 b 2f
42
43 .global memset
44 .type memset,%function
45memset:
46 add r0, r0, r2 @ we'll write backwards in memory
47 ands r3, r0, #3 @ 1 unaligned?
48 bne 1b @ 1
492:
50/*
51 * we know that the pointer in r0 is aligned to a word boundary.
52 */
53 orr r1, r1, r1, lsl #8
54 orr r1, r1, r1, lsl #16
55 mov r3, r1
56 cmp r2, #16
57 blt 5f
58/*
59 * We need an extra register for this loop - save the return address and
60 * use the LR
61 */
62 str lr, [sp, #-4]!
63 mov ip, r1
64 mov lr, r1
65
663: subs r2, r2, #64
67 stmgedb r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
68 stmgedb r0!, {r1, r3, ip, lr}
69 stmgedb r0!, {r1, r3, ip, lr}
70 stmgedb r0!, {r1, r3, ip, lr}
71 bgt 3b
72 ldrpc cond=eq @ Now <64 bytes to go.
73/*
74 * No need to correct the count; we're only testing bits from now on
75 */
76 tst r2, #32
77 stmnedb r0!, {r1, r3, ip, lr}
78 stmnedb r0!, {r1, r3, ip, lr}
79 tst r2, #16
80 stmnedb r0!, {r1, r3, ip, lr}
81 ldr lr, [sp], #4
82
835: tst r2, #8
84 stmnedb r0!, {r1, r3}
85 tst r2, #4
86 strne r1, [r0, #-4]!
87/*
88 * When we get here, we've got less than 4 bytes to zero. We
89 * may have an unaligned pointer as well.
90 */
916: tst r2, #2
92 strneb r1, [r0, #-1]!
93 strneb r1, [r0, #-1]!
94 tst r2, #1
95 strneb r1, [r0, #-1]!
96 bx lr
97.end:
98 .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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_STDDEF__ 21#ifndef __HWSTUB_STDDEF__
22#define __HWEMUL_STDDEF__ 22#define __HWSTUB_STDDEF__
23 23
24#include "stdint.h" 24#include "stdint.h"
25 25
@@ -29,4 +29,4 @@ typedef int32_t ssize_t;
29#define MIN(a, b) ((a) < (b) ? (a) : (b)) 29#define MIN(a, b) ((a) < (b) ? (a) : (b))
30#define MAX(a, b) ((a) > (b) ? (a) : (b)) 30#define MAX(a, b) ((a) > (b) ? (a) : (b))
31 31
32#endif /* __HWEMUL_STDDEF__ */ 32#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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_STRING__ 21#ifndef __HWSTUB_STRING__
22#define __HWEMUL_STRING__ 22#define __HWSTUB_STRING__
23 23
24#include "stddef.h" 24#include "stddef.h"
25 25
@@ -27,4 +27,4 @@ void memset(void *dst, int c, size_t n);
27void memcpy(void *dst, const void *src, size_t n); 27void memcpy(void *dst, const void *src, size_t n);
28size_t strlen(const char *s); 28size_t strlen(const char *s);
29 29
30#endif /* __HWEMUL_STRING__ */ 30#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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __HWEMUL_SYSTEM__ 21#ifndef __HWSTUB_SYSTEM__
22#define __HWEMUL_SYSTEM__ 22#define __HWSTUB_SYSTEM__
23 23
24#define IRQ_ENABLED 0x00 24#define IRQ_ENABLED 0x00
25#define IRQ_DISABLED 0x80 25#define IRQ_DISABLED 0x80
@@ -114,5 +114,5 @@ static inline int disable_interrupt_save(int mask)
114 return cpsr; 114 return cpsr;
115} 115}
116 116
117#endif /* __HWEMUL_SYSTEM__ */ 117#endif /* __HWSTUB_SYSTEM__ */
118 118
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 @@
1CC=gcc 1CC=gcc
2AR=ar 2CXX=g++
3HWEMUL_LIB_DIR=../lib 3LD=g++
4CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWEMUL_LIB_DIR) 4HWSTUB_LIB_DIR=../lib
5LDFLAGS=`pkg-config --libs libusb-1.0` -lreadline 5REGTOOLS_LIB_DIR=../../regtools/lib
6EXEC=hwemul_tool 6CFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2`
7HWEMUL_LIB=$(HWEMUL_LIB_DIR)/libhwemul.a 7CXXFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2`
8LDFLAGS=`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`
9EXEC=hwstub_shell hwstub_load
8SRC=$(wildcard *.c) 10SRC=$(wildcard *.c)
9OBJ=$(SRC:.c=.o) 11SRCXX=$(wildcard *.cpp)
12OBJ=$(SRC:.c=.o) $(SRCXX:.cpp=.o)
13LIBS=$(HWSTUB_LIB_DIR)/libhwstub.a $(REGTOOLS_LIB_DIR)/libsocdesc.a
10 14
11all: $(EXEC) 15all: $(EXEC)
12 16
17$(HWSTUB_LIB_DIR)/libhwstub.a:
18 make -C $(HWSTUB_LIB_DIR)
19
20$(REGTOOLS_LIB_DIR)/libsocdesc.a:
21 make -C $(REGTOOLS_LIB_DIR)
22
13%.o: %.c 23%.o: %.c
14 $(CC) $(CFLAGS) -c -o $@ $< 24 $(CC) $(CFLAGS) -c -o $@ $<
15 25
16hwemul_tool: hwemul_tool.o $(HWEMUL_LIB) 26%.o: %.cpp
17 $(CC) -o $@ $^ $(LDFLAGS) 27 $(CXX) $(CXXFLAGS) -c -o $@ $<
28
29hwstub_shell: hwstub_shell.o $(LIBS)
30 $(LD) -o $@ $^ $(LDFLAGS)
31
32hwstub_load: hwstub_load.o $(LIBS)
33 $(LD) -o $@ $^ $(LDFLAGS)
18 34
19clean: 35clean:
20 rm -rf $(OBJ) $(LIB) 36 rm -rf $(OBJ) $(LIB) $(EXEC)
21 37
22 38
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "hwemul.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27#include <readline/readline.h>
28#include <readline/history.h>
29
30bool g_quiet = false;
31struct hwemul_device_t hwdev;
32struct hwemul_soc_t *cur_soc = NULL;
33
34void print_log(struct hwemul_device_t *hwdev)
35{
36 do
37 {
38 char buffer[128];
39 int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
40 if(length <= 0)
41 break;
42 buffer[length] = 0;
43 printf("%s", buffer);
44 }while(1);
45}
46
47int print_help()
48{
49 printf("Commands:\n");
50 printf(" help\t\tDisplay this help\n");
51 printf(" call <addr>\tCall address <addr>\n");
52 printf(" quit\t\tQuit this session\n");
53 printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
54 printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
55 printf(" read <regname>\tRead a register by name\n");
56 printf(" read <regname>.<field>\tRead a register field by name\n");
57 printf(" soc <socname>\tSelect the soc description to use\n");
58 printf(" write <value> <regname>\tWrite a register by name\n");
59 printf(" write <value <regname>.<field>\tWrite a register field by name\n");
60 printf(" NOTE: if the register is SCT variant, no read is performed.\n");
61 return 1;
62}
63
64int syntax_error(char *str)
65{
66 printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
67 return 1;
68}
69
70int parse_uint32(char *str, uint32_t *u)
71{
72 char *end;
73 *u = strtoul(str, &end, 0);
74 return *end == 0;
75}
76
77int do_call(uint32_t a)
78{
79 hwemul_call(&hwdev, a);
80 return 1;
81}
82
83int parse_call()
84{
85 char *arg = strtok(NULL, " ");
86 uint32_t addr;
87 if(arg && parse_uint32(arg, &addr))
88 return do_call(addr);
89 else
90 return syntax_error(arg);
91}
92
93int do_read32(uint32_t a)
94{
95 uint32_t val;
96 if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
97 printf("%#x = %#x\n", a, val);
98 else
99 printf("read error at %#x\n", a);
100 return 1;
101}
102
103int parse_read32()
104{
105 char *arg = strtok(NULL, " ");
106 uint32_t addr;
107 if(arg && parse_uint32(arg, &addr))
108 return do_read32(addr);
109 else
110 return syntax_error(arg);
111}
112
113int do_write32(uint32_t val, uint32_t a)
114{
115 if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
116 printf("data written\n");
117 else
118 printf("write error at %#x\n", a);
119 return 1;
120}
121
122int parse_write32()
123{
124 char *arg = strtok(NULL, " ");
125 uint32_t val;
126 if(!arg || !parse_uint32(arg, &val))
127 return syntax_error(arg);
128 uint32_t addr;
129 arg = strtok(NULL, " ");
130 if(arg && parse_uint32(arg, &addr))
131 return do_write32(val, addr);
132 else
133 return syntax_error(arg);
134}
135
136struct hwemul_soc_t *find_soc_by_name(const char *soc)
137{
138 struct hwemul_soc_list_t *list = hwemul_get_soc_list();
139 for(size_t i = 0; i < list->nr_socs; i++)
140 if(strcmp(soc, list->socs[i]->name) == 0)
141 return list->socs[i];
142 return NULL;
143}
144
145struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
146{
147 for(size_t i = 0; i < soc->nr_regs; i++)
148 if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
149 return soc->regs_by_name[i];
150 return NULL;
151}
152
153struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
154{
155 for(size_t i = 0; i < reg->nr_fields; i++)
156 if(strcmp(field, reg->fields_by_name[i]->name) == 0)
157 return reg->fields_by_name[i];
158 return NULL;
159}
160
161
162int do_read(char *regname)
163{
164 char *dot = strchr(regname, '.');
165 if(dot != NULL)
166 *dot++ = 0;
167 if(cur_soc == NULL)
168 {
169 printf("No soc selected!\n");
170 return 1;
171 }
172 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
173 if(reg == NULL)
174 {
175 printf("no reg '%s' found\n", regname);
176 return 1;
177 }
178 uint32_t val;
179 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
180 {
181 printf("read error at %#x\n", reg->addr);
182 return 1;
183 }
184 if(dot)
185 {
186 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
187 if(field == NULL)
188 {
189 printf("no field '%s' found\n", dot);
190 return 1;
191 }
192 val >>= field->first_bit;
193 val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
194 printf("%s.%s = %#x\n", regname, dot, val);
195 }
196 else
197 printf("%s = %#x\n", regname, val);
198 return 1;
199}
200
201int parse_read()
202{
203 char *arg = strtok(NULL, " ");
204 if(arg)
205 return do_read(arg);
206 else
207 return syntax_error(arg);
208}
209
210int do_soc(char *soc)
211{
212 struct hwemul_soc_t *s = find_soc_by_name(soc);
213 if(s == NULL)
214 printf("no soc '%s' found\n", soc);
215 else
216 cur_soc = s;
217 return 1;
218}
219
220int parse_soc()
221{
222 char *arg = strtok(NULL, " ");
223 if(arg)
224 return do_soc(arg);
225 else
226 return syntax_error(arg);
227}
228
229int do_write(uint32_t val, char *regname)
230{
231 char *dot = strchr(regname, '.');
232 if(dot != NULL)
233 *dot++ = 0;
234 if(cur_soc == NULL)
235 {
236 printf("No soc selected!\n");
237 return 1;
238 }
239 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
240 int is_sct = 0;
241 uint32_t addr_off = 0;
242 if(reg == NULL)
243 {
244 size_t len = strlen(regname);
245 /* try SCT variant */
246 if(strcmp(regname + len - 4, "_SET") == 0)
247 addr_off = 4;
248 else if(strcmp(regname + len - 4, "_CLR") == 0)
249 addr_off = 8;
250 else if(strcmp(regname + len - 4, "_TOG") == 0)
251 addr_off = 12;
252 else
253 {
254 printf("no reg '%s' found\n", regname);
255 return 1;
256 }
257 is_sct = 1;
258 regname[len - 4] = 0;
259 reg = find_reg_by_name(cur_soc, regname);
260 if(reg == NULL)
261 {
262 printf("no reg '%s' found\n", regname);
263 return 1;
264 }
265 }
266 if(dot)
267 {
268 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
269 if(field == NULL)
270 {
271 printf("no field '%s' found\n", dot);
272 return 1;
273 }
274 uint32_t actual_val = 0;
275 if(!is_sct)
276 {
277 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
278 {
279 printf("read error at %#x\n", reg->addr);
280 return 1;
281 }
282 printf("read %#x at %#x\n", actual_val, reg->addr);
283 }
284 uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
285 printf("mask=%#x\n", mask);
286 val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
287 }
288 printf("write %#x to %#x\n", val, reg->addr + addr_off);
289 if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
290 {
291 printf("write error at %#x\n", reg->addr);
292 return 1;
293 }
294 return 1;
295}
296
297int parse_write()
298{
299 char *arg = strtok(NULL, " ");
300 uint32_t val;
301 if(!arg || !parse_uint32(arg, &val))
302 return syntax_error(arg);
303 arg = strtok(NULL, " ");
304 if(arg)
305 return do_write(val, arg);
306 else
307 return syntax_error(arg);
308}
309
310int parse_command(char *cmd)
311{
312 if(strcmp(cmd, "help") == 0)
313 return print_help();
314 if(strcmp(cmd, "quit") == 0)
315 return 0;
316 if(strcmp(cmd, "call") == 0)
317 return parse_call();
318 if(strcmp(cmd, "read32") == 0)
319 return parse_read32();
320 if(strcmp(cmd, "write32") == 0)
321 return parse_write32();
322 if(strcmp(cmd, "read") == 0)
323 return parse_read();
324 if(strcmp(cmd, "soc") == 0)
325 return parse_soc();
326 if(strcmp(cmd, "write") == 0)
327 return parse_write();
328 return syntax_error(cmd);
329}
330
331void interactive_mode(void)
332{
333 rl_bind_key('\t', rl_complete);
334 while(1)
335 {
336 char *input = readline("> ");
337 if(!input)
338 break;
339 add_history(input);
340 int ret = parse_command(input);
341 free(input);
342 if(ret == 0)
343 break;
344 }
345}
346
347void usage(void)
348{
349 printf("hwemul_tool, compiled with hwemul %d.%d.%d\n",
350 HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, HWEMUL_VERSION_REV);
351 printf("available soc descriptions:");
352 for(unsigned i = 0; i < hwemul_get_soc_list()->nr_socs; i++)
353 printf(" %s", hwemul_get_soc_list()->socs[i]->name);
354 printf("\n");
355 printf("usage: hwemul_tool [options]\n");
356 printf("options:\n");
357 printf(" --help/-?\tDisplay this help\n");
358 printf(" --quiet/-q\tQuiet non-command messages\n");
359 exit(1);
360}
361
362int main(int argc, char **argv)
363{
364 while(1)
365 {
366 static struct option long_options[] =
367 {
368 {"help", no_argument, 0, '?'},
369 {"quiet", no_argument, 0, 'q'},
370 {0, 0, 0, 0}
371 };
372
373 int c = getopt_long(argc, argv, "?q", long_options, NULL);
374 if(c == -1)
375 break;
376 switch(c)
377 {
378 case -1:
379 break;
380 case 'q':
381 g_quiet = true;
382 break;
383 case '?':
384 usage();
385 break;
386 default:
387 abort();
388 }
389 }
390
391 if(argc - optind != 0)
392 {
393 usage();
394 return 1;
395 }
396
397 libusb_context *ctx;
398 libusb_init(&ctx);
399 libusb_set_debug(ctx, 3);
400
401 if(!g_quiet)
402 printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID, HWEMUL_USB_PID);
403
404 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
405 HWEMUL_USB_VID, HWEMUL_USB_PID);
406 if(handle == NULL)
407 {
408 printf("No device found\n");
409 return 1;
410 }
411
412 libusb_device *mydev = libusb_get_device(handle);
413 if(!g_quiet)
414 {
415 printf("device found at %d:%d\n",
416 libusb_get_bus_number(mydev),
417 libusb_get_device_address(mydev));
418 }
419 hwdev.handle = handle;
420 if(hwemul_probe(&hwdev))
421 {
422 printf("Cannot probe device!\n");
423 return 1;
424 }
425
426 struct usb_resp_info_version_t ver;
427 int ret = hwemul_get_info(&hwdev, HWEMUL_INFO_VERSION, &ver, sizeof(ver));
428 if(ret != sizeof(ver))
429 {
430 printf("Cannot get version!\n");
431 goto Lerr;
432 }
433 if(!g_quiet)
434 printf("Device version: %d.%d.%d\n", ver.major, ver.minor, ver.revision);
435
436 struct usb_resp_info_layout_t layout;
437 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_LAYOUT, &layout, sizeof(layout));
438 if(ret != sizeof(layout))
439 {
440 printf("Cannot get layout: %d\n", ret);
441 goto Lerr;
442 }
443 if(!g_quiet)
444 {
445 printf("Device layout:\n");
446 printf(" Code: 0x%x (0x%x)\n", layout.oc_code_start, layout.oc_code_size);
447 printf(" Stack: 0x%x (0x%x)\n", layout.oc_stack_start, layout.oc_stack_size);
448 printf(" Buffer: 0x%x (0x%x)\n", layout.oc_buffer_start, layout.oc_buffer_size);
449 }
450
451 struct usb_resp_info_features_t features;
452 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_FEATURES, &features, sizeof(features));
453 if(ret != sizeof(features))
454 {
455 printf("Cannot get features: %d\n", ret);
456 goto Lerr;
457 }
458 if(!g_quiet)
459 {
460 printf("Device features:");
461 if(features.feature_mask & HWEMUL_FEATURE_LOG)
462 printf(" log");
463 if(features.feature_mask & HWEMUL_FEATURE_MEM)
464 printf(" mem");
465 if(features.feature_mask & HWEMUL_FEATURE_CALL)
466 printf(" call");
467 if(features.feature_mask & HWEMUL_FEATURE_JUMP)
468 printf(" jump");
469 if(features.feature_mask & HWEMUL_FEATURE_AES_OTP)
470 printf(" aes_otp");
471 printf("\n");
472 }
473
474 struct usb_resp_info_stmp_t stmp;
475 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_STMP, &stmp, sizeof(stmp));
476 if(ret != sizeof(stmp))
477 {
478 printf("Cannot get stmp: %d\n", ret);
479 goto Lerr;
480 }
481 if(!g_quiet)
482 {
483 printf("Device stmp:\n");
484 printf(" chip ID: %x (%s)\n", stmp.chipid,hwemul_get_product_string(&stmp));
485 printf(" revision: %d (%s)\n", stmp.rev, hwemul_get_rev_string(&stmp));
486 printf(" supported: %d\n", stmp.is_supported);
487 }
488
489 if(!g_quiet)
490 {
491 void *rom = malloc(64 * 1024);
492 ret = hwemul_rw_mem(&hwdev, 1, 0xc0000000, rom, 64 * 1024);
493 if(ret != 64 * 1024)
494 {
495 printf("Cannot read ROM: %d\n", ret);
496 goto Lerr;
497 }
498
499 printf("ROM successfully read!\n");
500 FILE *f = fopen("rom.bin", "wb");
501 fwrite(rom, 64 * 1024, 1, f);
502 fclose(f);
503 }
504
505 if(!g_quiet)
506 {
507 struct
508 {
509 uint8_t iv[16];
510 uint8_t data[16];
511 } __attribute__((packed)) dcp_test;
512
513 for(int i = 0; i < 16; i++)
514 dcp_test.iv[i] = rand();
515 for(int i = 0; i < 16; i++)
516 dcp_test.data[i] = rand();
517 printf("DCP\n");
518 printf(" IN\n");
519 printf(" IV:");
520 for(int i = 0; i < 16; i++)
521 printf(" %02x", dcp_test.iv[i]);
522 printf("\n");
523 printf(" IV:");
524 for(int i = 0; i < 16; i++)
525 printf(" %02x", dcp_test.data[i]);
526 printf("\n");
527
528 if(!hwemul_aes_otp(&hwdev, &dcp_test, sizeof(dcp_test), HWEMUL_AES_OTP_ENCRYPT))
529 {
530 printf(" OUT\n");
531 printf(" IV:");
532 for(int i = 0; i < 16; i++)
533 printf(" %02x", dcp_test.iv[i]);
534 printf("\n");
535 printf(" IV:");
536 for(int i = 0; i < 16; i++)
537 printf(" %02x", dcp_test.data[i]);
538 printf("\n");
539 }
540 else
541 printf("DCP error!\n");
542 }
543
544 if(!g_quiet)
545 printf("Starting interactive session. Type 'help' to get help.\n");
546
547 interactive_mode();
548
549 Lerr:
550 if(features.feature_mask & HWEMUL_FEATURE_LOG)
551 {
552 if(!g_quiet)
553 printf("Device log:\n");
554 print_log(&hwdev);
555 }
556 hwemul_release(&hwdev);
557 return 1;
558}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "hwstub.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27#include <ctype.h>
28
29struct player_info_t
30{
31 const char *name;
32 const char *username;
33 int modelnum;
34};
35
36enum image_type_t
37{
38 IT_RAW,
39 IT_ROCKBOX,
40 IT_DETECT,
41 /* positive values reserved for rockbox-specific models */
42};
43
44struct player_info_t players[] =
45{
46 { "zenv", "Zen V", 85 },
47 { "zmoz", "Zen Mozaic", 87 },
48 { "zen", "Zen", 88 },
49 { "zxfi", "Zen X-Fi", 86 },
50 { NULL, 0 },
51};
52
53enum image_type_t detect_type(unsigned char *buffer, size_t size)
54{
55 if(size < 8)
56 return IT_RAW;
57 int player;
58 for(player = 0; players[player].name; player++)
59 if(memcmp(buffer + 4, players[player].name, 4) == 0)
60 break;
61 if(players[player].name == NULL)
62 return IT_RAW;
63 unsigned long checksum = players[player].modelnum;
64 for(size_t i = 8; i < size; i++)
65 checksum += buffer[i];
66 unsigned long expected = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
67 if(checksum != expected)
68 return IT_RAW;
69 return IT_ROCKBOX;
70}
71
72const char *get_player_name(unsigned char *buffer)
73{
74 for(int player = 0; players[player].name; player++)
75 if(memcmp(buffer, players[player].name, 4) == 0)
76 return players[player].username;
77 return NULL;
78}
79
80bool could_be_rockbox(unsigned char *buffer, size_t size)
81{
82 /* usually target use 3 or 4 digits */
83 if(size >= 8 && isprint(buffer[4]) && isprint(buffer[5]) && isprint(buffer[6]) &&
84 (isprint(buffer[7]) || buffer[7] == 0))
85 {
86 unsigned long checksum = 0;
87 for(size_t i = 8; i < size; i++)
88 checksum += buffer[i];
89 unsigned long expected = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
90 unsigned long expected_modelnm = expected - checksum;
91 if(expected_modelnm < 150)
92 fprintf(stderr, "This file looks like a valid rockbox image but I don't know this player: %.4s (modelnum=%ld)\n",
93 buffer + 4, expected_modelnm);
94 else
95 fprintf(stderr, "This file could be a valid rockbox image but I don't know this player and the checksum is strange: %.4s\n",
96 buffer + 4);
97 return true;
98 }
99 else
100 return false;
101}
102
103void usage(void)
104{
105 printf("usage: hwstub_load [options] <addr> <file>\n");
106 printf("options:\n");
107 printf(" --help/-? Display this help\n");
108 printf(" --quiet/-q Quiet output\n");
109 printf(" --type/-t <t> Override file type\n");
110 printf("file types:\n");
111 printf(" raw Load a raw binary blob\n");
112 printf(" rockbox Load a rockbox image produced by scramble\n");
113 printf(" detect Try to guess the format\n");
114 printf("known players:");
115 for(int i = 0; players[i].name; i++)
116 printf(" %s", players[i].name);
117 printf("\n");
118 exit(1);
119}
120
121int main(int argc, char **argv)
122{
123 bool quiet = false;
124 struct hwstub_device_t hwdev;
125 enum image_type_t type = IT_DETECT;
126
127 // parse command line
128 while(1)
129 {
130 static struct option long_options[] =
131 {
132 {"help", no_argument, 0, '?'},
133 {"quiet", no_argument, 0, 'q'},
134 {"type", required_argument, 0, 't'},
135 {0, 0, 0, 0}
136 };
137
138 int c = getopt_long(argc, argv, "?qt:", long_options, NULL);
139 if(c == -1)
140 break;
141 switch(c)
142 {
143 case -1:
144 break;
145 case 'q':
146 quiet = true;
147 break;
148 case '?':
149 usage();
150 break;
151 case 't':
152 if(strcmp(optarg, "raw") == 0)
153 type = IT_RAW;
154 else if(strcmp(optarg, "rockbox") == 0)
155 type = IT_ROCKBOX;
156 else if(strcmp(optarg, "detect") == 0)
157 type = IT_DETECT;
158 else
159 {
160 fprintf(stderr, "Unknown file type '%s'\n", optarg);
161 return 1;
162 }
163 break;
164 default:
165 abort();
166 }
167 }
168
169 if(optind + 2 != argc)
170 usage();
171
172 char *end;
173 unsigned long addr = strtoul(argv[optind], &end, 0);
174 if(*end)
175 {
176 fprintf(stderr, "Invalid load address\n");
177 return 2;
178 }
179
180 FILE *f = fopen(argv[optind + 1], "rb");
181 if(f == NULL)
182 {
183 fprintf(stderr, "Cannot open file for reading: %m\n");
184 return 3;
185 }
186 fseek(f, 0, SEEK_END);
187 size_t size = ftell(f);
188 fseek(f, 0, SEEK_SET);
189 unsigned char *buffer = (unsigned char*)malloc(size);
190 fread(buffer, size, 1, f);
191 fclose(f);
192
193 if(type == IT_ROCKBOX || type == IT_DETECT)
194 {
195 enum image_type_t det = detect_type(buffer, size);
196 if(type == IT_ROCKBOX && det != IT_ROCKBOX)
197 {
198 if(!could_be_rockbox(buffer, size))
199 fprintf(stderr, "This file does not appear to be valid rockbox image.\n");
200 return 4;
201 }
202 if(type == IT_DETECT && det == IT_RAW)
203 could_be_rockbox(buffer, size);
204 type = det;
205 if(type == IT_ROCKBOX)
206 {
207 if(!quiet)
208 printf("Rockox image is for player %s (%.4s)\n", get_player_name(buffer + 4), buffer + 4);
209 memmove(buffer, buffer + 8, size - 8);
210 size -= 8;
211 }
212 }
213
214 if(!quiet)
215 {
216 if(type == IT_RAW)
217 printf("Loading raw image at %#lx\n", addr);
218 else
219 printf("Loading rockbox image at %#lx\n", addr);
220 }
221
222 // create usb context
223 libusb_context *ctx;
224 libusb_init(&ctx);
225 libusb_set_debug(ctx, 3);
226
227 // look for device
228 if(!quiet)
229 printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID);
230
231 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
232 HWSTUB_USB_VID, HWSTUB_USB_PID);
233 if(handle == NULL)
234 {
235 fprintf(stderr, "No device found\n");
236 return 1;
237 }
238
239 // admin stuff
240 libusb_device *mydev = libusb_get_device(handle);
241 if(!quiet)
242 {
243 printf("device found at %d:%d\n",
244 libusb_get_bus_number(mydev),
245 libusb_get_device_address(mydev));
246 }
247 hwdev.handle = handle;
248 if(hwstub_probe(&hwdev))
249 {
250 fprintf(stderr, "Cannot probe device!\n");
251 return 1;
252 }
253
254 // get hwstub information
255 struct usb_resp_info_version_t hwdev_ver;
256 int ret = hwstub_get_info(&hwdev, HWSTUB_INFO_VERSION, &hwdev_ver, sizeof(hwdev_ver));
257 if(ret != sizeof(hwdev_ver))
258 {
259 fprintf(stderr, "Cannot get version!\n");
260 goto Lerr;
261 }
262 if(hwdev_ver.major != HWSTUB_VERSION_MAJOR || hwdev_ver.minor < HWSTUB_VERSION_MINOR)
263 {
264 printf("Warning: this tool is possibly incompatible with your device:\n");
265 printf("Device version: %d.%d.%d\n", hwdev_ver.major, hwdev_ver.minor, hwdev_ver.revision);
266 printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
267 }
268
269 // get features
270 struct usb_resp_info_features_t hwdev_features;
271 ret = hwstub_get_info(&hwdev, HWSTUB_INFO_FEATURES, &hwdev_features, sizeof(hwdev_features));
272 if(ret != sizeof(hwdev_features))
273 {
274 fprintf(stderr, "Cannot get features: %d\n", ret);
275 goto Lerr;
276 }
277 if(!(hwdev_features.feature_mask & HWSTUB_RW_MEM))
278 {
279 fprintf(stderr, "Device doesn't support R/W commands\n");
280 goto Lerr;
281 }
282 if(!(hwdev_features.feature_mask & HWSTUB_JUMP))
283 {
284 fprintf(stderr, "Device doesn't support jump commands\n");
285 goto Lerr;
286 }
287 ret = hwstub_rw_mem(&hwdev, 0, addr, buffer, size);
288 if(ret != (int)size)
289 {
290 fprintf(stderr, "Image write failed\n");
291 goto Lerr;
292 }
293 hwstub_jump(&hwdev, addr);
294
295 hwstub_release(&hwdev);
296 return 0;
297
298 Lerr:
299 // display log if handled
300 if(hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
301 {
302 fprintf(stderr, "Device log:\n");
303 do
304 {
305 char buffer[128];
306 int length = hwstub_get_log(&hwdev, buffer, sizeof(buffer) - 1);
307 if(length <= 0)
308 break;
309 buffer[length] = 0;
310 fprintf(stderr, "%s", buffer);
311 }while(1);
312 }
313 hwstub_release(&hwdev);
314 return 1;
315}
316
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "hwstub.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27#include <readline/readline.h>
28#include <readline/history.h>
29#include <lua.hpp>
30#include "soc_desc.hpp"
31
32#if LUA_VERSION_NUM < 502
33#warning You need at least lua 5.2
34#endif
35
36/**
37 * Global variables
38 */
39bool g_quiet = false;
40struct hwstub_device_t g_hwdev;
41struct usb_resp_info_version_t g_hwdev_ver;
42struct usb_resp_info_layout_t g_hwdev_layout;
43struct usb_resp_info_features_t g_hwdev_features;
44struct usb_resp_info_stmp_t g_hwdev_stmp;
45lua_State *g_lua;
46
47/**
48 * hw specific
49 */
50
51void print_log(struct hwstub_device_t *hwdev)
52{
53 do
54 {
55 char buffer[128];
56 int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1);
57 if(length <= 0)
58 break;
59 buffer[length] = 0;
60 printf("%s", buffer);
61 }while(1);
62}
63
64/**
65 * Lua specific
66 */
67int my_lua_help(lua_State *state)
68{
69 bool has_sub = false;
70 // implement help() in C so that we do not rely on the init to implement it
71 // help can take optional arguments
72 int n = lua_gettop(state);
73
74 lua_getglobal(state, "hwstub");
75 if(!lua_istable(state, -1))
76 goto Lerr;
77 lua_getfield(state, -1, "help");
78 if(!lua_istable(state, -1))
79 goto Lerr;
80
81 for(int i = 1; i <= n; i++)
82 {
83 lua_pushvalue(state, i);
84 lua_gettable(state, -2);
85 if(lua_isnil(state, -1))
86 {
87 printf("I don't know subtopic '%s'!\n", lua_tostring(state, i));
88 return 0;
89 }
90 if(!lua_istable(state, -1))
91 {
92 printf("Subtopic '%s' is not a table!\n", lua_tostring(state, i));
93 return 0;
94 }
95 }
96
97 printf("================[ HELP ");
98 for(int i = 1; i <= n; i++)
99 printf("> %s ", lua_tostring(state, i));
100 printf("]================\n");
101
102 lua_pushnil(state);
103 while(lua_next(state, -2))
104 {
105 // key is at -2 and value at -1
106 if(lua_isstring(state, -1))
107 printf("%s\n", lua_tostring(state, -1));
108 else if(lua_istable(state, -1))
109 has_sub = true;
110 // pop value but keep key
111 lua_pop(state, 1);
112 }
113
114 if(has_sub)
115 {
116 printf("\n");
117 printf("You can get more information on the following subtopics:\n");
118 lua_pushnil(state);
119 while(lua_next(state, -2))
120 {
121 // key is at -2 and value at -1
122 if(lua_istable(state, -1))
123 printf("* %s\n", lua_tostring(state, -2));
124 // pop value but keep key
125 lua_pop(state, 1);
126 }
127 }
128 printf("================[ STOP ]================\n");
129
130 return 0;
131
132 Lerr:
133 printf("There is a problem with the Lua context. Help is expected to be in hwstub.help\n");
134 printf("You must have messed badly the environment.\n");
135 return 0;
136}
137
138typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr);
139typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val);
140
141soc_word_t hw_read8(lua_State *state, soc_addr_t addr)
142{
143 uint8_t u;
144 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
145 luaL_error(state, "fail to read8 @ %p", addr);
146 return u;
147}
148
149soc_word_t hw_read16(lua_State *state, soc_addr_t addr)
150{
151 uint16_t u;
152 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
153 luaL_error(state, "fail to read16 @ %p", addr);
154 return u;
155}
156
157soc_word_t hw_read32(lua_State *state, soc_addr_t addr)
158{
159 uint32_t u;
160 if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
161 luaL_error(state, "fail to read32 @ %p", addr);
162 return u;
163}
164
165void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val)
166{
167 uint8_t u = val;
168 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
169 luaL_error(state, "fail to write8 @ %p", addr);
170}
171
172void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val)
173{
174 uint16_t u = val;
175 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
176 luaL_error(state, "fail to write16 @ %p", addr);
177}
178
179void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val)
180{
181 uint32_t u = val;
182 if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
183 luaL_error(state, "fail to write32 @ %p", addr);
184}
185
186int my_lua_readn(lua_State *state)
187{
188 hw_readn_fn_t fn = (hw_readn_fn_t)lua_touserdata(state, lua_upvalueindex(1));
189 int n = lua_gettop(state);
190 if(n != 1)
191 luaL_error(state, "readn takes a single argument");
192 lua_pushunsigned(state, fn(state, luaL_checkunsigned(state, 1)));
193 return 1;
194}
195
196int my_lua_writen(lua_State *state)
197{
198 hw_writen_fn_t fn = (hw_writen_fn_t)lua_touserdata(state, lua_upvalueindex(1));
199 int n = lua_gettop(state);
200 if(n != 2)
201 luaL_error(state, "writen takes two arguments");
202 fn(state, luaL_checkunsigned(state, 1), luaL_checkunsigned(state, 2));
203 return 0;
204}
205
206int my_lua_printlog(lua_State *state)
207{
208 print_log(&g_hwdev);
209 return 0;
210}
211
212bool my_lua_import_hwstub()
213{
214 int oldtop = lua_gettop(g_lua);
215
216 lua_newtable(g_lua); // hwstub
217
218 lua_newtable(g_lua); // options
219 lua_pushboolean(g_lua, g_quiet);
220 lua_setfield(g_lua, -2, "quiet");
221 lua_setfield(g_lua, -2, "options");
222
223 lua_newtable(g_lua); // dev
224 lua_newtable(g_lua); // version
225 lua_pushinteger(g_lua, g_hwdev_ver.major);
226 lua_setfield(g_lua, -2, "major");
227 lua_pushinteger(g_lua, g_hwdev_ver.minor);
228 lua_setfield(g_lua, -2, "minor");
229 lua_pushinteger(g_lua, g_hwdev_ver.revision);
230 lua_setfield(g_lua, -2, "revision");
231 lua_setfield(g_lua, -2, "version");
232
233 lua_newtable(g_lua); // layout
234 lua_newtable(g_lua); // ocram
235 lua_newtable(g_lua); // code
236 lua_pushinteger(g_lua, g_hwdev_layout.oc_code_start);
237 lua_setfield(g_lua, -2, "start");
238 lua_pushinteger(g_lua, g_hwdev_layout.oc_code_size);
239 lua_setfield(g_lua, -2, "size");
240 lua_setfield(g_lua, -2, "code");
241 lua_newtable(g_lua); // stack
242 lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_start);
243 lua_setfield(g_lua, -2, "start");
244 lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_size);
245 lua_setfield(g_lua, -2, "size");
246 lua_setfield(g_lua, -2, "stack");
247 lua_newtable(g_lua); // buffer
248 lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_start);
249 lua_setfield(g_lua, -2, "start");
250 lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_size);
251 lua_setfield(g_lua, -2, "size");
252 lua_setfield(g_lua, -2, "buffer");
253 lua_setfield(g_lua, -2, "ocram");
254 lua_setfield(g_lua, -2, "layout");
255
256 lua_newtable(g_lua); // stmp
257 lua_pushinteger(g_lua, g_hwdev_stmp.chipid);
258 lua_setfield(g_lua, -2, "chipid");
259 lua_pushinteger(g_lua, g_hwdev_stmp.rev);
260 lua_setfield(g_lua, -2, "rev");
261 lua_setfield(g_lua, -2, "stmp");
262
263 lua_newtable(g_lua); // features
264 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG));
265 lua_setfield(g_lua, -2, "log");
266 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_MEM));
267 lua_setfield(g_lua, -2, "mem");
268 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_CALL));
269 lua_setfield(g_lua, -2, "call");
270 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_JUMP));
271 lua_setfield(g_lua, -2, "jump");
272 lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_AES_OTP));
273 lua_setfield(g_lua, -2, "aes_otp");
274 lua_setfield(g_lua, -2, "features");
275
276 lua_pushlightuserdata(g_lua, (void *)&hw_read8);
277 lua_pushcclosure(g_lua, my_lua_readn, 1);
278 lua_setfield(g_lua, -2, "read8");
279 lua_pushlightuserdata(g_lua, (void *)&hw_read16);
280 lua_pushcclosure(g_lua, my_lua_readn, 1);
281 lua_setfield(g_lua, -2, "read16");
282 lua_pushlightuserdata(g_lua, (void *)&hw_read32);
283 lua_pushcclosure(g_lua, my_lua_readn, 1);
284 lua_setfield(g_lua, -2, "read32");
285
286 lua_pushlightuserdata(g_lua, (void *)&hw_write8);
287 lua_pushcclosure(g_lua, my_lua_writen, 1);
288 lua_setfield(g_lua, -2, "write8");
289 lua_pushlightuserdata(g_lua, (void *)&hw_write16);
290 lua_pushcclosure(g_lua, my_lua_writen, 1);
291 lua_setfield(g_lua, -2, "write16");
292 lua_pushlightuserdata(g_lua, (void *)&hw_write32);
293 lua_pushcclosure(g_lua, my_lua_writen, 1);
294 lua_setfield(g_lua, -2, "write32");
295 lua_pushcclosure(g_lua, my_lua_printlog, 0);
296 lua_setfield(g_lua, -2, "print_log");
297
298 lua_setfield(g_lua, -2, "dev");
299
300 lua_newtable(g_lua); // host
301 lua_newtable(g_lua); // version
302 lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR);
303 lua_setfield(g_lua, -2, "major");
304 lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR);
305 lua_setfield(g_lua, -2, "minor");
306 lua_pushinteger(g_lua, HWSTUB_VERSION_REV);
307 lua_setfield(g_lua, -2, "revision");
308 lua_setfield(g_lua, -2, "version");
309 lua_setfield(g_lua, -2, "host");
310
311 lua_newtable(g_lua); // soc
312 lua_setfield(g_lua, -2, "soc");
313
314 lua_newtable(g_lua); // help
315 lua_pushinteger(g_lua, 1);
316 lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands.");
317 lua_settable(g_lua, -3);
318 lua_pushinteger(g_lua, 2);
319 lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on.");
320 lua_settable(g_lua, -3);
321 lua_pushinteger(g_lua, 3);
322 lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z).");
323 lua_settable(g_lua, -3);
324 lua_pushinteger(g_lua, 4);
325 lua_pushstring(g_lua, "Example: help(\"hwstub\").");
326 lua_settable(g_lua, -3);
327 lua_setfield(g_lua, -2, "help");
328
329 lua_setglobal(g_lua, "hwstub");
330
331 lua_pushcfunction(g_lua, my_lua_help);
332 lua_setglobal(g_lua, "help");
333
334 if(lua_gettop(g_lua) != oldtop)
335 {
336 printf("internal error: unbalanced my_lua_import_soc");
337 return false;
338 }
339 return true;
340}
341
342int my_lua_read_reg(lua_State *state)
343{
344 int n = lua_gettop(state);
345 if(n != 0)
346 luaL_error(state, "read() takes no argument");
347 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
348 lua_pushunsigned(state, hw_read32(state, addr));
349 return 1;
350}
351
352int my_lua_write_reg(lua_State *state)
353{
354 int n = lua_gettop(state);
355 if(n != 1)
356 luaL_error(state, "write() takes one argument");
357 soc_word_t val = luaL_checkunsigned(state, 1);
358 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
359 hw_write32(state, addr, val);
360 return 0;
361}
362
363int my_lua_read_field(lua_State *state)
364{
365 int n = lua_gettop(state);
366 if(n != 0)
367 luaL_error(state, "read() takes no argument");
368 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
369 soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
370 soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
371 lua_pushunsigned(state, (hw_read32(state, addr) >> shift) & mask);
372 return 1;
373}
374
375int my_lua_write_field(lua_State *state)
376{
377 int n = lua_gettop(state);
378 if(n != 0 && n!= 1)
379 luaL_error(state, "write() takes one or no argument");
380 soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1));
381 soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2));
382 soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3));
383 bool is_sct = lua_toboolean(state, lua_upvalueindex(5));
384
385 soc_word_t value = mask;
386 if(n == 1)
387 {
388 if(!lua_isnumber(state, 1) && lua_isstring(state, 1))
389 {
390 lua_pushvalue(state, lua_upvalueindex(4));
391 lua_pushvalue(state, 1);
392 lua_gettable(state, -2);
393 if(lua_isnil(state, -1))
394 luaL_error(state, "field has no value %s", lua_tostring(state, 1));
395 value = luaL_checkunsigned(state, -1);
396 lua_pop(state, 2);
397 }
398 else
399 value = luaL_checkunsigned(state, 1);
400 value &= mask;
401 }
402
403 if(!is_sct)
404 value = value << shift | (hw_read32(state, addr) & ~(mask << shift));
405 else
406 value <<= shift;
407
408 hw_write32(state, addr, value);
409 return 0;
410}
411
412void my_lua_create_field(soc_addr_t addr, const soc_reg_field_t& field, bool sct)
413{
414 lua_newtable(g_lua);
415
416 lua_pushstring(g_lua, field.name.c_str());
417 lua_setfield(g_lua, -2, "name");
418
419 lua_pushunsigned(g_lua, addr);
420 lua_setfield(g_lua, -2, "addr");
421
422 lua_pushboolean(g_lua, sct);
423 lua_setfield(g_lua, -2, "sct");
424
425 lua_pushunsigned(g_lua, field.first_bit);
426 lua_setfield(g_lua, -2, "first_bit");
427
428 lua_pushunsigned(g_lua, field.last_bit);
429 lua_setfield(g_lua, -2, "last_bit");
430
431 lua_pushunsigned(g_lua, field.bitmask());
432 lua_setfield(g_lua, -2, "bitmask");
433
434 soc_word_t local_bitmask = field.bitmask() >> field.first_bit;
435 lua_pushunsigned(g_lua, local_bitmask);
436 lua_setfield(g_lua, -2, "local_bitmask");
437
438 lua_pushunsigned(g_lua, addr);
439 lua_pushunsigned(g_lua, field.first_bit);
440 lua_pushunsigned(g_lua, local_bitmask);
441 lua_pushcclosure(g_lua, my_lua_read_field, 3);
442 lua_setfield(g_lua, -2, "read");
443
444 lua_pushunsigned(g_lua, addr);
445 lua_pushunsigned(g_lua, field.first_bit);
446 lua_pushunsigned(g_lua, local_bitmask);
447 lua_pushvalue(g_lua, -4);
448 lua_pushboolean(g_lua, false);
449 lua_pushcclosure(g_lua, my_lua_write_field, 5);
450 lua_setfield(g_lua, -2, "write");
451
452 if(sct)
453 {
454 lua_pushunsigned(g_lua, addr + 4);
455 lua_pushunsigned(g_lua, field.first_bit);
456 lua_pushunsigned(g_lua, local_bitmask);
457 lua_pushvalue(g_lua, -4);
458 lua_pushboolean(g_lua, true);
459 lua_pushcclosure(g_lua, my_lua_write_field, 5);
460 lua_setfield(g_lua, -2, "set");
461
462 lua_pushunsigned(g_lua, addr + 8);
463 lua_pushunsigned(g_lua, field.first_bit);
464 lua_pushunsigned(g_lua, local_bitmask);
465 lua_pushvalue(g_lua, -4);
466 lua_pushboolean(g_lua, true);
467 lua_pushcclosure(g_lua, my_lua_write_field, 5);
468 lua_setfield(g_lua, -2, "clr");
469
470 lua_pushunsigned(g_lua, addr + 12);
471 lua_pushunsigned(g_lua, field.first_bit);
472 lua_pushunsigned(g_lua, local_bitmask);
473 lua_pushvalue(g_lua, -4);
474 lua_pushboolean(g_lua, true);
475 lua_pushcclosure(g_lua, my_lua_write_field, 5);
476 lua_setfield(g_lua, -2, "tog");
477 }
478
479 for(size_t i = 0; i < field.value.size(); i++)
480 {
481 lua_pushunsigned(g_lua, field.value[i].value);
482 lua_setfield(g_lua, -2, field.value[i].name.c_str());
483 }
484}
485
486void my_lua_create_reg(soc_addr_t addr, size_t index, const soc_reg_t& reg)
487{
488 lua_newtable(g_lua);
489
490 lua_pushstring(g_lua, reg.addr[index].name.c_str());
491 lua_setfield(g_lua, -2, "name");
492
493 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
494 lua_setfield(g_lua, -2, "addr");
495
496 lua_pushboolean(g_lua, !!(reg.flags & REG_HAS_SCT));
497 lua_setfield(g_lua, -2, "sct");
498
499 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
500 lua_pushcclosure(g_lua, my_lua_read_reg, 1);
501 lua_setfield(g_lua, -2, "read");
502
503 lua_pushunsigned(g_lua, addr + reg.addr[index].addr);
504 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
505 lua_setfield(g_lua, -2, "write");
506
507 if(reg.flags & REG_HAS_SCT)
508 {
509 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 4);
510 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
511 lua_setfield(g_lua, -2, "set");
512
513 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 8);
514 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
515 lua_setfield(g_lua, -2, "clr");
516
517 lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 12);
518 lua_pushcclosure(g_lua, my_lua_write_reg, 1);
519 lua_setfield(g_lua, -2, "tog");
520 }
521
522 for(size_t i = 0; i < reg.field.size(); i++)
523 {
524 my_lua_create_field(addr + reg.addr[index].addr, reg.field[i],
525 reg.flags & REG_HAS_SCT);
526 lua_setfield(g_lua, -2, reg.field[i].name.c_str());
527 }
528}
529
530void my_lua_create_dev(size_t index, const soc_dev_t& dev)
531{
532 lua_newtable(g_lua);
533
534 lua_pushstring(g_lua, dev.addr[index].name.c_str());
535 lua_setfield(g_lua, -2, "name");
536
537 lua_pushunsigned(g_lua, dev.addr[index].addr);
538 lua_setfield(g_lua, -2, "addr");
539
540 for(size_t i = 0; i < dev.reg.size(); i++)
541 {
542 bool table = dev.reg[i].addr.size() > 1;
543 if(table)
544 lua_newtable(g_lua);
545 else
546 lua_pushnil(g_lua);
547
548 for(size_t k = 0; k < dev.reg[i].addr.size(); k++)
549 {
550 my_lua_create_reg(dev.addr[index].addr, k, dev.reg[i]);
551 if(table)
552 {
553 lua_pushinteger(g_lua, k);
554 lua_pushvalue(g_lua, -2);
555 lua_settable(g_lua, -4);
556 }
557 lua_setfield(g_lua, -3, dev.reg[i].addr[k].name.c_str());
558 }
559
560 if(table)
561 lua_setfield(g_lua, -2, dev.reg[i].name.c_str());
562 else
563 lua_pop(g_lua, 1);
564 }
565}
566
567bool my_lua_import_soc(const soc_t& soc)
568{
569 int oldtop = lua_gettop(g_lua);
570
571 lua_getglobal(g_lua, "hwstub");
572 lua_getfield(g_lua, -1, "soc");
573
574 lua_newtable(g_lua);
575
576 lua_pushstring(g_lua, soc.name.c_str());
577 lua_setfield(g_lua, -2, "name");
578
579 lua_pushstring(g_lua, soc.desc.c_str());
580 lua_setfield(g_lua, -2, "desc");
581
582 for(size_t i = 0; i < soc.dev.size(); i++)
583 {
584 bool table = soc.dev[i].addr.size() > 1;
585 if(table)
586 lua_newtable(g_lua);
587 else
588 lua_pushnil(g_lua);
589
590 for(size_t k = 0; k < soc.dev[i].addr.size(); k++)
591 {
592 my_lua_create_dev(k, soc.dev[i]);
593 if(table)
594 {
595 lua_pushinteger(g_lua, k + 1);
596 lua_pushvalue(g_lua, -2);
597 lua_settable(g_lua, -4);
598 }
599 lua_setfield(g_lua, -3, soc.dev[i].addr[k].name.c_str());
600 }
601
602 if(table)
603 lua_setfield(g_lua, -2, soc.dev[i].name.c_str());
604 else
605 lua_pop(g_lua, 1);
606 }
607
608 lua_setfield(g_lua, -2, soc.name.c_str());
609
610 lua_pop(g_lua, 2);
611
612 if(lua_gettop(g_lua) != oldtop)
613 {
614 printf("internal error: unbalanced my_lua_import_soc\n");
615 return false;
616 }
617 return true;
618}
619
620bool my_lua_import_soc(const std::vector< soc_t >& socs)
621{
622 for(size_t i = 0; i < socs.size(); i++)
623 {
624 if(!g_quiet)
625 printf("importing %s...\n", socs[i].name.c_str());
626 if(!my_lua_import_soc(socs[i]))
627 return false;
628 }
629 return true;
630}
631
632/**
633 * glue
634 */
635
636void usage(void)
637{
638 printf("hwstub_tool, compiled with hwstub %d.%d.%d\n",
639 HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
640 printf("\n");
641 printf("usage: hwstub_tool [options] <soc desc files>\n");
642 printf("options:\n");
643 printf(" --help/-?\tDisplay this help\n");
644 printf(" --quiet/-q\tQuiet non-command messages\n");
645 printf(" -i <init>\tSet lua init file (default is init.lua)\n");
646 exit(1);
647}
648
649int main(int argc, char **argv)
650{
651 const char *lua_init = "init.lua";
652 // parse command line
653 while(1)
654 {
655 static struct option long_options[] =
656 {
657 {"help", no_argument, 0, '?'},
658 {"quiet", no_argument, 0, 'q'},
659 {0, 0, 0, 0}
660 };
661
662 int c = getopt_long(argc, argv, "?qi:", long_options, NULL);
663 if(c == -1)
664 break;
665 switch(c)
666 {
667 case -1:
668 break;
669 case 'q':
670 g_quiet = true;
671 break;
672 case '?':
673 usage();
674 break;
675 case 'i':
676 lua_init = optarg;
677 break;
678 default:
679 abort();
680 }
681 }
682
683 // load register descriptions
684 std::vector< soc_t > socs;
685 for(int i = optind; i < argc; i++)
686 if(!soc_desc_parse_xml(argv[i], socs))
687 {
688 printf("Cannot load description '%s'\n", argv[i]);
689 return 2;
690 }
691
692 // create usb context
693 libusb_context *ctx;
694 libusb_init(&ctx);
695 libusb_set_debug(ctx, 3);
696
697 // look for device
698 if(!g_quiet)
699 printf("Looking for device %#04x:%#04x...\n", HWSTUB_USB_VID, HWSTUB_USB_PID);
700
701 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
702 HWSTUB_USB_VID, HWSTUB_USB_PID);
703 if(handle == NULL)
704 {
705 printf("No device found\n");
706 return 1;
707 }
708
709 // admin stuff
710 libusb_device *mydev = libusb_get_device(handle);
711 if(!g_quiet)
712 {
713 printf("device found at %d:%d\n",
714 libusb_get_bus_number(mydev),
715 libusb_get_device_address(mydev));
716 }
717 g_hwdev.handle = handle;
718 if(hwstub_probe(&g_hwdev))
719 {
720 printf("Cannot probe device!\n");
721 return 1;
722 }
723
724 // get hwstub information
725 int ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
726 if(ret != sizeof(g_hwdev_ver))
727 {
728 printf("Cannot get version!\n");
729 goto Lerr;
730 }
731 if(g_hwdev_ver.major != HWSTUB_VERSION_MAJOR || g_hwdev_ver.minor < HWSTUB_VERSION_MINOR)
732 {
733 printf("Warning: this tool is possibly incompatible with your device:\n");
734 printf("Device version: %d.%d.%d\n", g_hwdev_ver.major, g_hwdev_ver.minor, g_hwdev_ver.revision);
735 printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
736 }
737
738 // get memory layout information
739 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
740 if(ret != sizeof(g_hwdev_layout))
741 {
742 printf("Cannot get layout: %d\n", ret);
743 goto Lerr;
744 }
745
746 // get features
747 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_FEATURES, &g_hwdev_features, sizeof(g_hwdev_features));
748 if(ret != sizeof(g_hwdev_features))
749 {
750 printf("Cannot get features: %d\n", ret);
751 goto Lerr;
752 }
753
754 // get STMP specific information
755 ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
756 if(ret != sizeof(g_hwdev_stmp))
757 {
758 printf("Cannot get stmp: %d\n", ret);
759 goto Lerr;
760 }
761
762 // dump ROM
763 if(!g_quiet)
764 {
765 void *rom = malloc(64 * 1024);
766 ret = hwstub_rw_mem(&g_hwdev, 1, 0xc0000000, rom, 64 * 1024);
767 if(ret != 64 * 1024)
768 {
769 printf("Cannot read ROM: %d\n", ret);
770 goto Lerr;
771 }
772
773 printf("ROM successfully read!\n");
774 FILE *f = fopen("rom.bin", "wb");
775 fwrite(rom, 64 * 1024, 1, f);
776 fclose(f);
777 }
778
779 // test DCP
780#if 0
781 if(!g_quiet)
782 {
783 struct
784 {
785 uint8_t iv[16];
786 uint8_t data[16];
787 } __attribute__((packed)) dcp_test;
788
789 for(int i = 0; i < 16; i++)
790 dcp_test.iv[i] = rand();
791 for(int i = 0; i < 16; i++)
792 dcp_test.data[i] = rand();
793 printf("DCP\n");
794 printf(" IN\n");
795 printf(" IV:");
796 for(int i = 0; i < 16; i++)
797 printf(" %02x", dcp_test.iv[i]);
798 printf("\n");
799 printf(" IV:");
800 for(int i = 0; i < 16; i++)
801 printf(" %02x", dcp_test.data[i]);
802 printf("\n");
803
804 if(!hwstub_aes_otp(&g_hwdev, &dcp_test, sizeof(dcp_test), HWSTUB_AES_OTP_ENCRYPT))
805 {
806 printf(" OUT\n");
807 printf(" IV:");
808 for(int i = 0; i < 16; i++)
809 printf(" %02x", dcp_test.iv[i]);
810 printf("\n");
811 printf(" IV:");
812 for(int i = 0; i < 16; i++)
813 printf(" %02x", dcp_test.data[i]);
814 printf("\n");
815 }
816 else
817 printf("DCP error!\n");
818 }
819#endif
820
821 /** Init lua */
822
823 // create lua state
824 g_lua = luaL_newstate();
825 if(g_lua == NULL)
826 {
827 printf("Cannot create lua state\n");
828 return 1;
829 }
830 // import hwstub
831 if(!my_lua_import_hwstub())
832 printf("Cannot import hwstub description into Lua context\n");
833 // open all standard libraires
834 luaL_openlibs(g_lua);
835 // import socs
836 if(!my_lua_import_soc(socs))
837 printf("Cannot import SoC descriptions into Lua context\n");
838
839 if(luaL_dofile(g_lua, lua_init))
840 printf("error in init: %s\n", lua_tostring(g_lua, -1));
841 lua_pop(g_lua, lua_gettop(g_lua));
842
843 /** start interactive mode */
844 if(!g_quiet)
845 printf("Starting interactive lua session. Type 'help()' to get some help\n");
846
847 // use readline to provide some history and completion
848 rl_bind_key('\t', rl_complete);
849 while(1)
850 {
851 char *input = readline("> ");
852 if(!input)
853 break;
854 add_history(input);
855 // evaluate string
856 if(luaL_dostring(g_lua, input))
857 printf("error: %s\n", lua_tostring(g_lua, -1));
858 // pop everything to start from a clean stack
859 lua_pop(g_lua, lua_gettop(g_lua));
860 free(input);
861 }
862
863 Lerr:
864 // display log if handled
865 if(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
866 {
867 if(!g_quiet)
868 printf("Device log:\n");
869 print_log(&g_hwdev);
870 }
871 hwstub_release(&g_hwdev);
872 return 1;
873}
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 @@
1-- init code for hwstub_tools
2
3--
4-- HELP
5--
6HELP = hwstub.help
7
8function HELP:create_topic(name)
9 self[name] = { create_topic = HELP.create_topic, add = HELP.add, get_topic = HELP.get_topic }
10 return self[name]
11end
12
13function HELP:get_topic(name)
14 return self[name]
15end
16
17function HELP:add(text)
18 table.insert(self, text)
19end
20
21do
22 local h = HELP:create_topic("hwstub")
23 h:add("This tool uses a number of well-defined namespaces (tables) to organise its features.")
24 h:add("The hwstub table contains a number of information and functions related to the tool itself.")
25 h:add("Of particular interest are")
26 h:add("* hwstub.host which holds host specific information.")
27 h:add("* hwstub.dev which holds device specific information. See DEV")
28 h:add("* hwstub.help (aka HELP) which holds the help. See HELP.");
29 h:add("* hwstub.soc which holds soc specific information. See HW");
30
31 h = HELP:create_topic("HELP");
32 h:add("This variable redirects to hwstub.help and provides access to the help system.");
33 h:add("You can enhance the help using the following methods on any topic (including HELP itself).");
34 h:add("* t:create_topic(s) to create a new subtopic named s under topic t");
35 h:add("* t:add(s) to add a help line to topic t");
36 h:add("* t:get_topic(s) to get the subtopic s under topic t");
37
38 h = HELP:create_topic("DEV");
39 h:add("This variable redirects to hwstub.dev and provides direct access to the device.");
40 h:add("It contains some information about the device and the following methods.");
41 h:add("* read8/16/32(a) reads a 8/16/32-bit integer at address a");
42 h:add("* write8/16/32(a, v) writes the 8/16/32-bit integer v at address a");
43
44 h = HELP:create_topic("HW");
45 h:add("This variable redirects to the current soc under hwstub.soc and should be changed by calling hwstub:soc:select only.");
46 h:add("The complete register tree can be found under HW in a well organise fashion.");
47 h:add("* HW.dev points to device dev");
48 h:add("* HW.dev[i] points to device devi if there are several copies of the device at different addresses.");
49 h:add("* HW.dev.reg points to the register reg under dev");
50 h:add("* HW.dev.reg[i] points to the register regi if there are several copies.");
51 h:add("* HW.dev.reg.f points to the field f under register reg.");
52 h:add("* HW.dev.reg.f.v gives the value of named value v of field f.");
53 h:add("* All registers can be read using HW.dev.reg.read() and written using HW.dev.reg.write(v).");
54 h:add("* Register with a SCT variant also implement HW.dev.reg.set/clr/tog(v).");
55 h:add("* All register field can be read using HW.dev.reg.f.read() and written using HW.dev.reg.f.write(v).");
56 h:add("* Field writes can either give a integer or a named value to write(v).");
57 h:add("* Register with a SCT variant also implement HW.dev.reg.f.set/clr/tog(v) with the same properties.");
58 h:add("* All devices, registers and fields also have descriptions available such as addresses.");
59end
60
61--
62-- INFO
63--
64
65if not hwstub.options.quiet then
66 print("information")
67 print(" hwstub")
68 print(" version: " .. string.format("%d.%d.%d", hwstub.host.version.major,
69 hwstub.host.version.minor, hwstub.host.version.revision))
70 print(" device")
71 print(" version: " .. string.format("%d.%d.%d", hwstub.dev.version.major,
72 hwstub.dev.version.minor, hwstub.dev.version.revision))
73 print(" layout")
74 print(" on-chip ram")
75 print(" code: " .. string.format("%#x bytes @ %#x",
76 hwstub.dev.layout.ocram.code.size, hwstub.dev.layout.ocram.code.start))
77 print(" stack: " .. string.format("%#x bytes @ %#x",
78 hwstub.dev.layout.ocram.stack.size, hwstub.dev.layout.ocram.stack.start))
79 print(" buffer: " .. string.format("%#x bytes @ %#x",
80 hwstub.dev.layout.ocram.buffer.size, hwstub.dev.layout.ocram.buffer.start))
81 print(" features");
82 print(" log: " .. tostring(hwstub.dev.features.log))
83 print(" mem: " .. tostring(hwstub.dev.features.mem))
84 print(" call: " .. tostring(hwstub.dev.features.call))
85 print(" jump: " .. tostring(hwstub.dev.features.jump))
86 print(" aes_otp: " .. tostring(hwstub.dev.features.aes_otp))
87end
88
89--
90-- SOC
91--
92function hwstub.soc:select(soc)
93 if self[soc] == nil then return false end
94 print("Selecting soc " .. soc .. ". Redirecting HW to hwstub.soc." .. soc)
95 HW = self[soc]
96 return true
97end
98
99--
100-- DEV
101--
102DEV = hwstub.dev
103
104require "lua/load"