diff options
Diffstat (limited to 'utils/hwstub')
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 | ||
61 | struct usb_resp_info_version_t | 61 | struct 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 | ||
95 | struct usb_resp_info_features_t | 95 | struct 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 | |||
2 | AR=ar | 2 | AR=ar |
3 | CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC | 3 | CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC |
4 | LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC | 4 | LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC |
5 | LIB=libhwemul.a | 5 | LIB=libhwstub.a |
6 | REGTOOLS=../../regtools | 6 | SRC=$(wildcard *.c) |
7 | DESC=$(REGTOOLS)/desc | ||
8 | HWEMULGEN=$(REGTOOLS)/hwemulgen | ||
9 | HWEMULSOC_PREFIX=hwemul_soc | ||
10 | SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c | ||
11 | OBJ=$(SRC:.c=.o) | 7 | OBJ=$(SRC:.c=.o) |
12 | 8 | ||
13 | all: $(LIB) $(EXEC) | 9 | all: $(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 | ||
24 | clean: | 17 | clean: |
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 */ |
29 | int hwemul_probe(struct hwemul_device_t *dev) | 28 | int 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 | ||
76 | int hwemul_release(struct hwemul_device_t *dev) | 75 | int 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 | ||
81 | int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz) | 80 | int 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 | ||
88 | int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz) | 87 | int 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 | ||
95 | int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) | 94 | int 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 | ||
115 | int hwemul_call(struct hwemul_device_t *dev, uint32_t addr) | 114 | int 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 | ||
123 | int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr) | 122 | int 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 | ||
131 | const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp) | 130 | const 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 | ||
142 | const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp) | 141 | const 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 | ||
162 | int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param) | 161 | int 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 | ||
28 | extern "C" { | ||
29 | #endif | ||
27 | 30 | ||
28 | /** | 31 | /** |
29 | * | 32 | * |
@@ -31,7 +34,7 @@ | |||
31 | * | 34 | * |
32 | */ | 35 | */ |
33 | 36 | ||
34 | struct hwemul_device_t | 37 | struct 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 */ |
44 | int hwemul_probe(struct hwemul_device_t *dev); | 47 | int hwstub_probe(struct hwstub_device_t *dev); |
45 | /* Returns 0 on success */ | 48 | /* Returns 0 on success */ |
46 | int hwemul_release(struct hwemul_device_t *dev); | 49 | int hwstub_release(struct hwstub_device_t *dev); |
47 | 50 | ||
48 | /* Returns number of bytes filled */ | 51 | /* Returns number of bytes filled */ |
49 | int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz); | 52 | int 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 */ |
51 | int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz); | 54 | int 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 */ |
53 | int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); | 56 | int 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 */ |
55 | int hwemul_call(struct hwemul_device_t *dev, uint32_t addr); | 58 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); |
56 | int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr); | 59 | int 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. */ |
58 | int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param); | 61 | int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param); |
62 | |||
63 | const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp); | ||
64 | const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp); | ||
59 | 65 | ||
60 | const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp); | 66 | #ifdef __cplusplus |
61 | const 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 @@ | |||
1 | PREFIX?=arm-elf-eabi- | 1 | # |
2 | CC=$(PREFIX)gcc | 2 | # common |
3 | LD=$(PREFIX)gcc | 3 | # |
4 | AS=$(PREFIX)gcc | 4 | CC=arm-elf-eabi-gcc |
5 | OC=$(PREFIX)objcopy | 5 | LD=arm-elf-eabi-gcc |
6 | SBTOOLS=../../sbtools/ | 6 | AS=arm-elf-eabi-gcc |
7 | OC=arm-elf-eabi-objcopy | ||
7 | CFLAGS=-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -mcpu=arm926ej-s -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init -ffunction-sections | 8 | CFLAGS=-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -mcpu=arm926ej-s -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init -ffunction-sections |
8 | CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700 | ||
9 | ASFLAGS=$(CFLAGS) -D__ASSEMBLER__ | 9 | ASFLAGS=$(CFLAGS) -D__ASSEMBLER__ |
10 | ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__ | ||
11 | OCFLAGS= | 10 | OCFLAGS= |
12 | LINKER_FILE=hwemul.lds | 11 | LINKER_FILE=hwstub.lds |
13 | LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map | 12 | TMP_LDS=link.lds |
14 | LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map | 13 | TMP_MAP=hwstub.map |
14 | LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP) | ||
15 | SRC_C=$(wildcard *.c) | 15 | SRC_C=$(wildcard *.c) |
16 | SRC_S=$(wildcard *.S) | 16 | SRC_S=$(wildcard *.S) |
17 | OBJ_C=$(SRC_C:.c=.o) | 17 | OBJ_C=$(SRC_C:.c=.o) |
18 | OBJ_S=$(SRC_S:.S=.o) | 18 | OBJ_S=$(SRC_S:.S=.o) |
19 | OBJ_C_3700=$(SRC_C:.c=.3700.o) | ||
20 | OBJ_S_3700=$(SRC_S:.S=.3700.o) | ||
21 | OBJ=$(OBJ_C) $(OBJ_S) | 19 | OBJ=$(OBJ_C) $(OBJ_S) |
22 | OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700) | ||
23 | OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ)) | 20 | OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ)) |
24 | OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700)) | ||
25 | DEPS=$(OBJ:.o=.d) | 21 | DEPS=$(OBJ:.o=.d) |
26 | EXEC_ELF=hwemul.elf | 22 | EXEC_ELF=hwstub.elf |
27 | EXEC_SB=hwemul.sb | ||
28 | EXEC_ELF_3700=hwemul3700.elf | ||
29 | EXEC_SB_3700=hwemul3700.sb | ||
30 | 23 | ||
24 | # | ||
25 | # image production | ||
26 | # | ||
27 | TOOLS=../../../tools | ||
28 | SBTOOLS=../../imxtools/sbtools | ||
29 | |||
30 | # sb (stmp37xx) | ||
31 | EXEC_SB=hwstub.sb | ||
31 | ELF2SB=$(SBTOOLS)/elftosb -d | 32 | ELF2SB=$(SBTOOLS)/elftosb -d |
32 | ELF2SB_CMD=-c hwemul.db | 33 | ELF2SB_CMD=-c hwstub.db |
33 | ELF2SB_KEY=-z | 34 | ELF2SB_KEY?=-z |
34 | SBLOADER=$(SBTOOLS)/sbloader | ||
35 | SBLOADER_CMD=0 $(EXEC_SB) | ||
36 | SBLOADER_CMD_3700=0 $(EXEC_SB_3700) | ||
37 | 35 | ||
38 | TOOLS=../../../../tools/ | 36 | # sb1 (stmp36xx) |
39 | SCRAMBLE=$(TOOLS)/scramble | 37 | EXEC_SB1=hwstub.sb1 |
38 | ELF2SB1_CMD=-loadjump $(EXEC_ELF) | ||
39 | ELF2SB1_KEY?= | ||
40 | ELF2SB1=$(SBTOOLS)/elftosb1 -d | ||
40 | 41 | ||
41 | EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700) | 42 | EXEC=$(EXEC_ELF) $(EXEC_SB) $(EXEC_SB1) |
42 | 43 | ||
43 | all: $(EXEC) | 44 | all: $(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 | ||
70 | link.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 | |||
85 | sbload: $(EXEC_SB) | ||
86 | $(SBLOADER) $(SBLOADER_CMD) | ||
87 | |||
88 | sbload3700: $(EXEC_SB_3700) | ||
89 | $(SBLOADER) $(SBLOADER_CMD_3700) | ||
90 | 71 | ||
91 | clean: | 72 | clean: |
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 | ||
26 | void vuprintf(int (*push)(void *userp, unsigned char data), | 26 | void 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 | ****************************************************************************/ |
21 | sources | 21 | sources |
22 | { | 22 | { |
23 | hwemul = "hwemul.elf"; | 23 | hwstub = "hwstub.elf"; |
24 | } | 24 | } |
25 | 25 | ||
26 | section(0) | 26 | section(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 | |||
2 | ENTRY(start) | ||
3 | OUTPUT_FORMAT(elf32-littlearm) | ||
4 | OUTPUT_ARCH(arm) | ||
5 | STARTUP(crt0.o) | ||
6 | |||
7 | |||
8 | |||
9 | MEMORY | ||
10 | { | ||
11 | OCRAM : ORIGIN = 0, LENGTH = 0x8000 | ||
12 | } | ||
13 | |||
14 | SECTIONS | ||
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); | |||
28 | void logf(const char *fmt, ...); | 28 | void logf(const char *fmt, ...); |
29 | size_t logf_readback(char *buf, size_t max_size); | 29 | size_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 | 41 | enum 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 | |||
78 | typedef void (*pin_irq_cb_t)(int bank, int pin); | ||
79 | |||
80 | static 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, | |
85 | static 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 | |||
91 | static 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 | |||
99 | static 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 | |||
107 | static 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 | |||
115 | static 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 | |||
123 | static 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 | |||
128 | static 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 | |||
134 | static 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 | ||
142 | static inline void imx233_enable_pin_pullup_mask(unsigned bank, uint32_t pin_msk, bool enable) | 50 | enum 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 | |||
644 | struct 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 | |||
691 | static 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 | |||
697 | static 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 | |||
717 | static 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 | |||
731 | static 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 | ||
855 | void memcpy(uint8_t *dst, const uint8_t *src, uint32_t length) | 505 | void memcpy(void *dest, const void *src, size_t n); |
856 | { | 506 | void memmove(void *dest, const void *src, size_t n); |
857 | for(uint32_t i = 0; i < length; i++) | 507 | void memset(void *dst, int value, size_t n); |
858 | dst[i] = src[i]; | ||
859 | } | ||
860 | |||
861 | void 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 | ||
1139 | struct usb_resp_info_version_t g_version = | 781 | struct 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 | ||
1146 | struct usb_resp_info_layout_t g_layout; | 788 | struct usb_resp_info_layout_t g_layout; |
@@ -1149,8 +791,8 @@ struct usb_resp_info_stmp_t g_stmp; | |||
1149 | 791 | ||
1150 | struct usb_resp_info_features_t g_features = | 792 | struct 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 | ||
1156 | static void fill_layout_info(void) | 798 | static 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 | ||
1258 | static void do_aes_otp(void *buffer, unsigned length, unsigned params) | 905 | static 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) | |||
1348 | void main(uint32_t arg) | 995 | void 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 | |||
46 | memcpy: | ||
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 | |||
56 | 1: subs r2, r2, #(28) | ||
57 | stmfd sp!, {r5 - r8} | ||
58 | blt 5f | ||
59 | |||
60 | 2: | ||
61 | 3: | ||
62 | 4: 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 | |||
67 | 5: ands ip, r2, #28 | ||
68 | rsb ip, ip, #32 | ||
69 | addne pc, pc, ip @ C is always clear here | ||
70 | b 7f | ||
71 | 6: 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 | |||
91 | 7: ldmfd sp!, {r5 - r8} | ||
92 | |||
93 | 8: 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 | |||
103 | 9: 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 | |||
116 | 10: 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 | |||
128 | 11: stmfd sp!, {r5 - r9} | ||
129 | |||
130 | 12: | ||
131 | 13: 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 | |||
155 | 14: ands ip, r2, #28 | ||
156 | beq 16f | ||
157 | |||
158 | 15: 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 | |||
165 | 16: sub r1, r1, #(\push / 8) | ||
166 | b 8b | ||
167 | |||
168 | .endm | ||
169 | |||
170 | |||
171 | forward_copy_shift pull=8 push=24 | ||
172 | |||
173 | 17: forward_copy_shift pull=16 push=16 | ||
174 | |||
175 | 18: 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 | |||
55 | memmove: | ||
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 | |||
71 | 1: subs r2, r2, #(28) | ||
72 | stmfd sp!, {r5 - r8} | ||
73 | blt 5f | ||
74 | |||
75 | 2: | ||
76 | 3: | ||
77 | 4: 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 | |||
82 | 5: ands ip, r2, #28 | ||
83 | rsb ip, ip, #32 | ||
84 | addne pc, pc, ip @ C is always clear here | ||
85 | b 7f | ||
86 | 6: 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 | |||
106 | 7: ldmfd sp!, {r5 - r8} | ||
107 | |||
108 | 8: 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 | |||
117 | 9: 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 | |||
129 | 10: 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 | |||
141 | 11: stmfd sp!, {r5 - r9} | ||
142 | |||
143 | 12: | ||
144 | 13: 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 | |||
168 | 14: ands ip, r2, #28 | ||
169 | beq 16f | ||
170 | |||
171 | 15: 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 | |||
178 | 16: add r1, r1, #(\pull / 8) | ||
179 | b 8b | ||
180 | |||
181 | .endm | ||
182 | |||
183 | |||
184 | backward_copy_shift push=8 pull=24 | ||
185 | |||
186 | 17: backward_copy_shift push=16 pull=16 | ||
187 | |||
188 | 18: 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 */ | ||
34 | 1: 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 | ||
45 | memset: | ||
46 | add r0, r0, r2 @ we'll write backwards in memory | ||
47 | ands r3, r0, #3 @ 1 unaligned? | ||
48 | bne 1b @ 1 | ||
49 | 2: | ||
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 | |||
66 | 3: 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 | |||
83 | 5: 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 | */ | ||
91 | 6: 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); | |||
27 | void memcpy(void *dst, const void *src, size_t n); | 27 | void memcpy(void *dst, const void *src, size_t n); |
28 | size_t strlen(const char *s); | 28 | size_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 @@ | |||
1 | CC=gcc | 1 | CC=gcc |
2 | AR=ar | 2 | CXX=g++ |
3 | HWEMUL_LIB_DIR=../lib | 3 | LD=g++ |
4 | CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWEMUL_LIB_DIR) | 4 | HWSTUB_LIB_DIR=../lib |
5 | LDFLAGS=`pkg-config --libs libusb-1.0` -lreadline | 5 | REGTOOLS_LIB_DIR=../../regtools/lib |
6 | EXEC=hwemul_tool | 6 | CFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2` |
7 | HWEMUL_LIB=$(HWEMUL_LIB_DIR)/libhwemul.a | 7 | CXXFLAGS=-Wall -O2 `pkg-config --cflags libusb-1.0` -g -I$(HWSTUB_LIB_DIR) -I$(REGTOOLS_LIB_DIR) `pkg-config --cflags lua5.2` |
8 | LDFLAGS=`pkg-config --libs libusb-1.0` `pkg-config --libs lua5.2` -lreadline -L$(HWSTUB_LIB_DIR) -L$(REGTOOLS_LIB_DIR) -lsocdesc -lhwstub `xml2-config --libs` | ||
9 | EXEC=hwstub_shell hwstub_load | ||
8 | SRC=$(wildcard *.c) | 10 | SRC=$(wildcard *.c) |
9 | OBJ=$(SRC:.c=.o) | 11 | SRCXX=$(wildcard *.cpp) |
12 | OBJ=$(SRC:.c=.o) $(SRCXX:.cpp=.o) | ||
13 | LIBS=$(HWSTUB_LIB_DIR)/libhwstub.a $(REGTOOLS_LIB_DIR)/libsocdesc.a | ||
10 | 14 | ||
11 | all: $(EXEC) | 15 | all: $(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 | ||
16 | hwemul_tool: hwemul_tool.o $(HWEMUL_LIB) | 26 | %.o: %.cpp |
17 | $(CC) -o $@ $^ $(LDFLAGS) | 27 | $(CXX) $(CXXFLAGS) -c -o $@ $< |
28 | |||
29 | hwstub_shell: hwstub_shell.o $(LIBS) | ||
30 | $(LD) -o $@ $^ $(LDFLAGS) | ||
31 | |||
32 | hwstub_load: hwstub_load.o $(LIBS) | ||
33 | $(LD) -o $@ $^ $(LDFLAGS) | ||
18 | 34 | ||
19 | clean: | 35 | clean: |
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 | |||
30 | bool g_quiet = false; | ||
31 | struct hwemul_device_t hwdev; | ||
32 | struct hwemul_soc_t *cur_soc = NULL; | ||
33 | |||
34 | void 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 | |||
47 | int 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 | |||
64 | int syntax_error(char *str) | ||
65 | { | ||
66 | printf("Syntax error at '%s'. Type 'help' to get some help.\n", str); | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | int parse_uint32(char *str, uint32_t *u) | ||
71 | { | ||
72 | char *end; | ||
73 | *u = strtoul(str, &end, 0); | ||
74 | return *end == 0; | ||
75 | } | ||
76 | |||
77 | int do_call(uint32_t a) | ||
78 | { | ||
79 | hwemul_call(&hwdev, a); | ||
80 | return 1; | ||
81 | } | ||
82 | |||
83 | int 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 | |||
93 | int 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 | |||
103 | int 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 | |||
113 | int 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 | |||
122 | int 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 | |||
136 | struct 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 | |||
145 | struct 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 | |||
153 | struct 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 | |||
162 | int 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 | |||
201 | int 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 | |||
210 | int 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 | |||
220 | int 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 | |||
229 | int 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 | |||
297 | int 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 | |||
310 | int 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 | |||
331 | void 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 | |||
347 | void 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 | |||
362 | int 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 | |||
29 | struct player_info_t | ||
30 | { | ||
31 | const char *name; | ||
32 | const char *username; | ||
33 | int modelnum; | ||
34 | }; | ||
35 | |||
36 | enum image_type_t | ||
37 | { | ||
38 | IT_RAW, | ||
39 | IT_ROCKBOX, | ||
40 | IT_DETECT, | ||
41 | /* positive values reserved for rockbox-specific models */ | ||
42 | }; | ||
43 | |||
44 | struct 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 | |||
53 | enum 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 | |||
72 | const 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 | |||
80 | bool 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 | |||
103 | void 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 | |||
121 | int 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 | */ | ||
39 | bool g_quiet = false; | ||
40 | struct hwstub_device_t g_hwdev; | ||
41 | struct usb_resp_info_version_t g_hwdev_ver; | ||
42 | struct usb_resp_info_layout_t g_hwdev_layout; | ||
43 | struct usb_resp_info_features_t g_hwdev_features; | ||
44 | struct usb_resp_info_stmp_t g_hwdev_stmp; | ||
45 | lua_State *g_lua; | ||
46 | |||
47 | /** | ||
48 | * hw specific | ||
49 | */ | ||
50 | |||
51 | void 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 | */ | ||
67 | int 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 | |||
138 | typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr); | ||
139 | typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val); | ||
140 | |||
141 | soc_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 | |||
149 | soc_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 | |||
157 | soc_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 | |||
165 | void 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 | |||
172 | void 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 | |||
179 | void 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 | |||
186 | int 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 | |||
196 | int 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 | |||
206 | int my_lua_printlog(lua_State *state) | ||
207 | { | ||
208 | print_log(&g_hwdev); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | bool 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 | |||
342 | int 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 | |||
352 | int 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 | |||
363 | int 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 | |||
375 | int 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 | |||
412 | void 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 | |||
486 | void 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 | |||
530 | void 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 | |||
567 | bool 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 | |||
620 | bool 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 | |||
636 | void 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 | |||
649 | int 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 | -- | ||
6 | HELP = hwstub.help | ||
7 | |||
8 | function HELP:create_topic(name) | ||
9 | self[name] = { create_topic = HELP.create_topic, add = HELP.add, get_topic = HELP.get_topic } | ||
10 | return self[name] | ||
11 | end | ||
12 | |||
13 | function HELP:get_topic(name) | ||
14 | return self[name] | ||
15 | end | ||
16 | |||
17 | function HELP:add(text) | ||
18 | table.insert(self, text) | ||
19 | end | ||
20 | |||
21 | do | ||
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."); | ||
59 | end | ||
60 | |||
61 | -- | ||
62 | -- INFO | ||
63 | -- | ||
64 | |||
65 | if 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)) | ||
87 | end | ||
88 | |||
89 | -- | ||
90 | -- SOC | ||
91 | -- | ||
92 | function 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 | ||
97 | end | ||
98 | |||
99 | -- | ||
100 | -- DEV | ||
101 | -- | ||
102 | DEV = hwstub.dev | ||
103 | |||
104 | require "lua/load" | ||