1
0
Fork 0
forked from len0rd/rockbox

imxtools: introduce hwemul

The hwemul tool is a small binary blob running on the device
that can received commands over USB. It is mainly intended to be
loaded using the recory mode and allows to read/write registers,
memory, use the OTP device, ... The tool is split into three
parts: dev/ contains the actual blob (which handles both imx233
and stmp3700), lib/ contains the communication library and can
also use the register description produced by the regtools/
to ease register by name, tools/ contains an interactive tool
to send commands to the device when running the blob.

Change-Id: Ie8cb32e987f825d8ed750d48071e43415b4dacb3
This commit is contained in:
Amaury Pouly 2012-11-14 12:51:51 +01:00
parent ec2153f2dd
commit f44d95630c
26 changed files with 3829 additions and 0 deletions

View file

@ -0,0 +1,91 @@
CC=arm-elf-eabi-gcc
LD=arm-elf-eabi-gcc
AS=arm-elf-eabi-gcc
OC=arm-elf-eabi-objcopy
SBTOOLS=../../sbtools/
CFLAGS=-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -mcpu=arm926ej-s -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init -ffunction-sections
CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700
ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__
OCFLAGS=
LINKER_FILE=hwemul.lds
LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map
LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map
SRC_C=$(wildcard *.c)
SRC_S=$(wildcard *.S)
OBJ_C=$(SRC_C:.c=.o)
OBJ_S=$(SRC_S:.S=.o)
OBJ_C_3700=$(SRC_C:.c=.3700.o)
OBJ_S_3700=$(SRC_S:.S=.3700.o)
OBJ=$(OBJ_C) $(OBJ_S)
OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700)
OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700))
DEPS=$(OBJ:.o=.d)
EXEC_ELF=hwemul.elf
EXEC_SB=hwemul.sb
EXEC_ELF_3700=hwemul3700.elf
EXEC_SB_3700=hwemul3700.sb
ELF2SB=$(SBTOOLS)/elftosb -d
ELF2SB_CMD=-c hwemul.db
ELF2SB_KEY=-z
SBLOADER=$(SBTOOLS)/sbloader
SBLOADER_CMD=0 $(EXEC_SB)
SBLOADER_CMD_3700=0 $(EXEC_SB_3700)
TOOLS=../../../../tools/
SCRAMBLE=$(TOOLS)/scramble
EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700)
all: $(EXEC)
# pull in dependency info for *existing* .o files
-include $(DEPS)
%.3700.o: %.c
$(CC) $(CFLAGS_3700) -c -o $@ $<
$(CC) -MM $(CFLAGS_3700) $*.c > $*.d
@cp -f $*.d $*.d.tmp
@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
@rm -f $*.d.tmp
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(CC) -MM $(CFLAGS) $*.c > $*.d
@cp -f $*.d $*.d.tmp
@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
@rm -f $*.d.tmp
%.3700.o: %.S
$(AS) $(ASFLAGS_3700) -c -o $@ $<
%.o: %.S
$(AS) $(ASFLAGS) -c -o $@ $<
link.lds: $(LINKER_FILE)
$(CC) -E -x c - < $< | sed '/#/d' > $@
$(EXEC_ELF): $(OBJ) link.lds
$(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
$(EXEC_SB): $(EXEC_ELF)
$(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
$(EXEC_ELF_3700): $(OBJ_3700) link.lds
$(LD) $(LDFLAGS_3700) -o $@ $(OBJ_EXCEPT_CRT0_3700)
$(EXEC_SB_3700): $(EXEC_ELF_3700)
$(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
sbload: $(EXEC_SB)
$(SBLOADER) $(SBLOADER_CMD)
sbload3700: $(EXEC_SB_3700)
$(SBLOADER) $(SBLOADER_CMD_3700)
clean:
rm -rf $(OBJ) $(OBJ_3700) $(DEPS) $(EXEC) *.map

View file

@ -0,0 +1,33 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_CONFIG__
#define __HWEMUL_CONFIG__
#define MEMORYSIZE 0
#define STACK_SIZE 0x1000
#define MAX_LOGF_SIZE 128
#define IRAM_ORIG 0
#define IRAM_SIZE 0x8000
#define DRAM_ORIG 0x40000000
#define DRAM_SIZE (MEMORYSIZE * 0x100000)
#endif /* __HWEMUL_CONFIG__ */

View file

@ -0,0 +1,17 @@
.section .text,"ax",%progbits
.code 32
.align 0x04
.global start
start:
msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
ldr sp, =oc_stackend
/* clear bss */
ldr r2, =bss_start
ldr r3, =bss_end
mov r4, #0
1:
cmp r3, r2
strhi r4, [r2], #4
bhi 1b
/* jump to C code */
b main

View file

@ -0,0 +1,223 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Gary Czvitkovicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdarg.h>
#include <limits.h>
#include "stddef.h"
#include "string.h"
#include "format.h"
static const char hexdigit[] = "0123456789ABCDEF";
void vuprintf(
/* call 'push()' for each output letter */
int (*push)(void *userp, unsigned char data),
void *userp,
const char *fmt,
va_list ap)
{
char *str;
char tmpbuf[12], pad;
int ch, width, val, sign, precision;
long lval, lsign;
unsigned int uval;
unsigned long ulval;
size_t uszval;
ssize_t szval, szsign;
bool ok = true;
tmpbuf[sizeof tmpbuf - 1] = '\0';
while ((ch = *fmt++) != '\0' && ok)
{
if (ch == '%')
{
ch = *fmt++;
pad = ' ';
if (ch == '0')
pad = '0';
width = 0;
while (ch >= '0' && ch <= '9')
{
width = 10*width + ch - '0';
ch = *fmt++;
}
precision = 0;
if(ch == '.')
{
ch = *fmt++;
while (ch >= '0' && ch <= '9')
{
precision = 10*precision + ch - '0';
ch = *fmt++;
}
} else {
precision = INT_MAX;
}
str = tmpbuf + sizeof tmpbuf - 1;
switch (ch)
{
case 'c':
*--str = va_arg (ap, int);
break;
case 's':
str = va_arg (ap, char*);
break;
case 'd':
val = sign = va_arg (ap, int);
if (val < 0)
val = -val;
do
{
*--str = (val % 10) + '0';
val /= 10;
}
while (val > 0);
if (sign < 0)
*--str = '-';
break;
case 'u':
uval = va_arg(ap, unsigned int);
do
{
*--str = (uval % 10) + '0';
uval /= 10;
}
while (uval > 0);
break;
case 'x':
case 'X':
pad='0';
uval = va_arg (ap, int);
do
{
*--str = hexdigit[uval & 0xf];
uval >>= 4;
}
while (uval);
break;
case 'l':
ch = *fmt++;
switch(ch) {
case 'x':
case 'X':
pad='0';
ulval = va_arg (ap, long);
do
{
*--str = hexdigit[ulval & 0xf];
ulval >>= 4;
}
while (ulval);
break;
case 'd':
lval = lsign = va_arg (ap, long);
if (lval < 0)
lval = -lval;
do
{
*--str = (lval % 10) + '0';
lval /= 10;
}
while (lval > 0);
if (lsign < 0)
*--str = '-';
break;
case 'u':
ulval = va_arg(ap, unsigned long);
do
{
*--str = (ulval % 10) + '0';
ulval /= 10;
}
while (ulval > 0);
break;
default:
*--str = 'l';
*--str = ch;
}
break;
case 'z':
ch = *fmt++;
switch(ch) {
case 'd':
szval = szsign = va_arg (ap, ssize_t);
if (szval < 0)
szval = -szval;
do
{
*--str = (szval % 10) + '0';
szval /= 10;
}
while (szval > 0);
if (szsign < 0)
*--str = '-';
break;
case 'u':
uszval = va_arg(ap, size_t);
do
{
*--str = (uszval % 10) + '0';
uszval /= 10;
}
while (uszval > 0);
break;
default:
*--str = 'z';
*--str = ch;
}
break;
default:
*--str = ch;
break;
}
if (width > 0)
{
width -= strlen (str);
while (width-- > 0 && ok)
ok=push(userp, pad);
}
while (*str != '\0' && ok && precision--)
ok=push(userp, *str++);
}
else
ok=push(userp, ch);
}
}

View file

@ -0,0 +1,29 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_FORMAT__
#define __HWEMUL_FORMAT__
#include <stdarg.h>
void vuprintf(int (*push)(void *userp, unsigned char data),
void *userp, const char *fmt, va_list ap);
#endif /* __HWEMUL_FORMAT__ */

View file

@ -0,0 +1,31 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
sources
{
hwemul = "hwemul.elf";
}
section(0)
{
load hwemul;
jump hwemul(1);
}

View file

@ -0,0 +1,70 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
ENTRY(start)
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
STARTUP(crt0.o)
#define IRAM_END_ADDR (IRAM_ORIG + IRAM_SIZE)
MEMORY
{
OCRAM : ORIGIN = IRAM_ORIG, LENGTH = IRAM_SIZE
}
SECTIONS
{
.octext :
{
oc_codestart = .;
*(.text*)
*(.data*)
*(.rodata*)
} > OCRAM
.bss (NOLOAD) :
{
bss_start = .;
*(.bss)
bss_end = .;
} > OCRAM
.stack (NOLOAD) :
{
oc_codeend = .;
oc_stackstart = .;
. += STACK_SIZE;
oc_stackend = .;
oc_bufferstart = .;
} > OCRAM
.ocend IRAM_END_ADDR (NOLOAD) :
{
oc_bufferend = .;
} > OCRAM
/DISCARD/ :
{
*(.eh_frame)
}
}

View file

@ -0,0 +1,49 @@
ENTRY(start)
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
STARTUP(crt0.o)
MEMORY
{
OCRAM : ORIGIN = 0, LENGTH = 0x8000
}
SECTIONS
{
.octext :
{
oc_codestart = .;
*(.text*)
*(.data*)
*(.rodata*)
} > OCRAM
.bss (NOLOAD) :
{
bss_start = .;
*(.bss)
bss_end = .;
} > OCRAM
.stack (NOLOAD) :
{
oc_codeend = .;
oc_stackstart = .;
. += 0x1000;
oc_stackend = .;
oc_bufferstart = .;
} > OCRAM
.ocend (0 + 0x8000) (NOLOAD) :
{
oc_bufferend = .;
} > OCRAM
/DISCARD/ :
{
*(.eh_frame)
}
}

View file

@ -0,0 +1,68 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "logf.h"
#include "format.h"
#include "string.h"
static unsigned char logfbuffer[MAX_LOGF_SIZE];
static int logfread = 0;
static int logfwrite = 0;
static int logfen = true;
void enable_logf(bool en)
{
logfen = en;
}
static int logf_push(void *userp, unsigned char c)
{
(void)userp;
logfbuffer[logfwrite++] = c;
if(logfwrite == MAX_LOGF_SIZE)
logfwrite = 0;
return true;
}
void logf(const char *fmt, ...)
{
if(!logfen) return;
va_list ap;
va_start(ap, fmt);
vuprintf(logf_push, NULL, fmt, ap);
va_end(ap);
}
size_t logf_readback(char *buf, size_t max_size)
{
if(logfread == logfwrite)
return 0;
if(logfread < logfwrite)
max_size = MIN(max_size, (size_t)(logfwrite - logfread));
else
max_size = MIN(max_size, (size_t)(MAX_LOGF_SIZE - logfread));
memcpy(buf, &logfbuffer[logfread], max_size);
logfread += max_size;
if(logfread == MAX_LOGF_SIZE)
logfread = 0;
return max_size;
}

View file

@ -0,0 +1,31 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_LOGF__
#define __HWEMUL_LOGF__
#include "stddef.h"
#include <stdarg.h>
void enable_logf(bool en);
void logf(const char *fmt, ...);
size_t logf_readback(char *buf, size_t max_size);
#endif /* __HWEMUL_LOGF__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
#include "../hwemul_protocol.h"

View file

@ -0,0 +1,32 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_STDDEF__
#define __HWEMUL_STDDEF__
#include "stdint.h"
typedef uint32_t size_t;
typedef int32_t ssize_t;
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* __HWEMUL_STDDEF__ */

View file

@ -0,0 +1,38 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __STDINT_H__
#define __STDINT_H__
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef char bool;
#define true 1
#define false 0
#define NULL (void *)0
#endif /* __STDINT_H__ */

View file

@ -0,0 +1,29 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "string.h"
size_t strlen(const char *s)
{
size_t len = 0;
while(*s++)
len++;
return len;
}

View file

@ -0,0 +1,30 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_STRING__
#define __HWEMUL_STRING__
#include "stddef.h"
void memset(void *dst, int c, size_t n);
void memcpy(void *dst, const void *src, size_t n);
size_t strlen(const char *s);
#endif /* __HWEMUL_STRING__ */

View file

@ -0,0 +1,118 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_SYSTEM__
#define __HWEMUL_SYSTEM__
#define IRQ_ENABLED 0x00
#define IRQ_DISABLED 0x80
#define IRQ_STATUS 0x80
#define FIQ_ENABLED 0x00
#define FIQ_DISABLED 0x40
#define FIQ_STATUS 0x40
#define IRQ_FIQ_ENABLED 0x00
#define IRQ_FIQ_DISABLED 0xc0
#define IRQ_FIQ_STATUS 0xc0
#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
#define set_irq_level(status) \
set_interrupt_status((status), IRQ_STATUS)
#define set_fiq_status(status) \
set_interrupt_status((status), FIQ_STATUS)
#define disable_irq_save() \
disable_interrupt_save(IRQ_STATUS)
#define disable_fiq_save() \
disable_interrupt_save(FIQ_STATUS)
#define restore_irq(cpsr) \
restore_interrupt(cpsr)
#define restore_fiq(cpsr) \
restore_interrupt(cpsr)
#define disable_irq() \
disable_interrupt(IRQ_STATUS)
#define enable_irq() \
enable_interrupt(IRQ_STATUS)
#define disable_fiq() \
disable_interrupt(FIQ_STATUS)
#define enable_fiq() \
enable_interrupt(FIQ_STATUS)
static inline int set_interrupt_status(int status, int mask)
{
unsigned long cpsr;
int oldstatus;
/* Read the old levels and set the new ones */
asm volatile (
"mrs %1, cpsr \n"
"bic %0, %1, %[mask] \n"
"orr %0, %0, %2 \n"
"msr cpsr_c, %0 \n"
: "=&r,r"(cpsr), "=&r,r"(oldstatus)
: "r,i"(status & mask), [mask]"i,i"(mask));
return oldstatus;
}
static inline void restore_interrupt(int cpsr)
{
/* Set cpsr_c from value returned by disable_interrupt_save
* or set_interrupt_status */
asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
}
static inline void enable_interrupt(int mask)
{
/* Clear I and/or F disable bit */
int tmp;
asm volatile (
"mrs %0, cpsr \n"
"bic %0, %0, %1 \n"
"msr cpsr_c, %0 \n"
: "=&r"(tmp) : "i"(mask));
}
static inline void disable_interrupt(int mask)
{
/* Set I and/or F disable bit */
int tmp;
asm volatile (
"mrs %0, cpsr \n"
"orr %0, %0, %1 \n"
"msr cpsr_c, %0 \n"
: "=&r"(tmp) : "i"(mask));
}
static inline int disable_interrupt_save(int mask)
{
/* Set I and/or F disable bit and return old cpsr value */
int cpsr, tmp;
asm volatile (
"mrs %1, cpsr \n"
"orr %0, %1, %2 \n"
"msr cpsr_c, %0 \n"
: "=&r"(tmp), "=&r"(cpsr)
: "i"(mask));
return cpsr;
}
#endif /* __HWEMUL_SYSTEM__ */

View file

@ -0,0 +1,454 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) by Linux Kernel Developers
*
* Based on code from the Linux Kernel
* available at http://www.kernel.org
* Original file: <kernel>/include/linux/usb/ch9.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
/*
* This file holds USB constants and structures that are needed for
* USB device APIs. These are used by the USB device model, which is
* defined in chapter 9 of the USB 2.0 specification and in the
* Wireless USB 1.0 (spread around). Linux has several APIs in C that
* need these:
*
* - the master/host side Linux-USB kernel driver API;
* - the "usbfs" user space API; and
* - the Linux "gadget" slave/device/peripheral side driver API.
*
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
* act either as a USB master/host or as a USB slave/device. That means
* the master and slave side APIs benefit from working well together.
*
* There's also "Wireless USB", using low power short range radios for
* peripheral interconnection but otherwise building on the USB framework.
*
* Note all descriptors are declared '__attribute__((packed))' so that:
*
* [a] they never get padded, either internally (USB spec writers
* probably handled that) or externally;
*
* [b] so that accessing bigger-than-a-bytes fields will never
* generate bus errors on any platform, even when the location of
* its descriptor inside a bundle isn't "naturally aligned", and
*
* [c] for consistency, removing all doubt even when it appears to
* someone that the two other points are non-issues for that
* particular descriptor type.
*/
#ifndef _CH9_H_
#define _CH9_H_
#include "stdint.h"
/*-------------------------------------------------------------------------*/
/* CONTROL REQUEST SUPPORT */
/*
* USB directions
*
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
* It's also one of three fields in control requests bRequestType.
*/
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
/*
* USB types, the second of three bRequestType fields
*/
#define USB_TYPE_MASK (0x03 << 5)
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
/*
* USB recipients, the third of three bRequestType fields
*/
#define USB_RECIP_MASK 0x1f
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/*
* Standard requests, for the bRequest field of a SETUP packet.
*
* These are qualified by the bRequestType field, so that for example
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
* by a GET_STATUS request.
*/
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
/*
* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
* are read as a bit array returned by USB_REQ_GET_STATUS. (So there
* are at most sixteen features of each type.) Hubs may also support a
* new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
*/
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
#define USB_DEVICE_BATTERY 2 /* (wireless) */
#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
/**
* struct usb_ctrlrequest - SETUP data for a USB device control request
* @bRequestType: matches the USB bmRequestType field
* @bRequest: matches the USB bRequest field
* @wValue: matches the USB wValue field (le16 byte order)
* @wIndex: matches the USB wIndex field (le16 byte order)
* @wLength: matches the USB wLength field (le16 byte order)
*
* This structure is used to send control requests to a USB device. It matches
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
* USB spec for a fuller description of the different fields, and what they are
* used for.
*
* Note that the driver for any interface can issue control requests.
* For most devices, interfaces don't coordinate with each other, so
* such requests may be made at any time.
*/
struct usb_ctrlrequest {
uint8_t bRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} __attribute__ ((packed));
/*-------------------------------------------------------------------------*/
/*
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
* (rarely) accepted by SET_DESCRIPTOR.
*
* Note that all multi-byte values here are encoded in little endian
* byte order "on the wire". But when exposed through Linux-USB APIs,
* they've been converted to cpu byte order.
*/
/*
* Descriptor types ... USB 2.0 spec table 9.5
*/
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_INTERFACE_POWER 0x08
/* these are from a minor usb 2.0 revision (ECN) */
#define USB_DT_OTG 0x09
#define USB_DT_DEBUG 0x0a
#define USB_DT_INTERFACE_ASSOCIATION 0x0b
/* these are from the Wireless USB spec */
#define USB_DT_SECURITY 0x0c
#define USB_DT_KEY 0x0d
#define USB_DT_ENCRYPTION_TYPE 0x0e
#define USB_DT_BOS 0x0f
#define USB_DT_DEVICE_CAPABILITY 0x10
#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
#define USB_DT_WIRE_ADAPTER 0x21
#define USB_DT_RPIPE 0x22
#define USB_DT_CS_RADIO_CONTROL 0x23
/* Conventional codes for class-specific descriptors. The convention is
* defined in the USB "Common Class" Spec (3.11). Individual class specs
* are authoritative for their usage, not the "common class" writeup.
*/
#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE)
#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG)
#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING)
#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE)
#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT)
/* All standard descriptors have these 2 fields at the beginning */
struct usb_descriptor_header {
uint8_t bLength;
uint8_t bDescriptorType;
} __attribute__ ((packed));
/*-------------------------------------------------------------------------*/
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} __attribute__ ((packed));
#define USB_DT_DEVICE_SIZE 18
/*
* Device and/or Interface Class codes
* as found in bDeviceClass or bInterfaceClass
* and defined by www.usb.org documents
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
/*-------------------------------------------------------------------------*/
/* USB_DT_CONFIG: Configuration descriptor information.
*
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
* descriptor type is different. Highspeed-capable devices can look
* different depending on what speed they're currently running. Only
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
* descriptors.
*/
struct usb_config_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} __attribute__ ((packed));
#define USB_DT_CONFIG_SIZE 9
/* from config descriptor bmAttributes */
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
/*-------------------------------------------------------------------------*/
/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wString[]; /* UTF-16LE encoded */
} __attribute__ ((packed));
/* note that "string" zero is special, it holds language codes that
* the device supports, not Unicode characters.
*/
/*-------------------------------------------------------------------------*/
/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} __attribute__ ((packed));
#define USB_DT_INTERFACE_SIZE 9
/*-------------------------------------------------------------------------*/
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} __attribute__ ((packed));
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
/*
* Endpoints
*/
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
/*-------------------------------------------------------------------------*/
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
struct usb_qualifier_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
uint8_t bRESERVED;
} __attribute__ ((packed));
/*-------------------------------------------------------------------------*/
/* USB_DT_OTG (from OTG 1.0a supplement) */
struct usb_otg_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bmAttributes; /* support for HNP, SRP, etc */
} __attribute__ ((packed));
/* from usb_otg_descriptor.bmAttributes */
#define USB_OTG_SRP (1 << 0)
#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
/*-------------------------------------------------------------------------*/
/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
struct usb_debug_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
/* bulk endpoints with 8 byte maxpacket */
uint8_t bDebugInEndpoint;
uint8_t bDebugOutEndpoint;
} __attribute__((packed));
/*-------------------------------------------------------------------------*/
/* USB 2.0 defines three speeds, here's how Linux identifies them */
enum usb_device_speed {
USB_SPEED_UNKNOWN = 0, /* enumerating */
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
USB_SPEED_HIGH, /* usb 2.0 */
USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
};
enum usb_device_state {
/* NOTATTACHED isn't in the USB spec, and this state acts
* the same as ATTACHED ... but it's clearer this way.
*/
USB_STATE_NOTATTACHED = 0,
/* chapter 9 and authentication (wireless) device states */
USB_STATE_ATTACHED,
USB_STATE_POWERED, /* wired */
USB_STATE_UNAUTHENTICATED, /* auth */
USB_STATE_RECONNECTING, /* auth */
USB_STATE_DEFAULT, /* limited function */
USB_STATE_ADDRESS,
USB_STATE_CONFIGURED, /* most functions */
USB_STATE_SUSPENDED
/* NOTE: there are actually four different SUSPENDED
* states, returning to POWERED, DEFAULT, ADDRESS, or
* CONFIGURED respectively when SOF tokens flow again.
* At this level there's no difference between L1 and L2
* suspend states. (L2 being original USB 1.1 suspend.)
*/
};
/**
* struct usb_string - wraps a C string and its USB id
* @id:the (nonzero) ID for this string
* @s:the string, in UTF-8 encoding
*
* If you're using usb_gadget_get_string(), use this to wrap a string
* together with its ID.
*/
struct usb_string {
uint8_t id;
const char* s;
};
/**
* struct usb_gadget_strings - a set of USB strings in a given language
* @language:identifies the strings' language (0x0409 for en-us)
* @strings:array of strings with their ids
*
* If you're using usb_gadget_get_string(), use this to wrap all the
* strings for a given language.
*/
struct usb_gadget_strings {
uint16_t language; /* 0x0409 for en-us */
struct usb_string* strings;
};
#endif /*_CH9_H_*/

View file

@ -0,0 +1,127 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL_PROTOCOL__
#define __HWEMUL_PROTOCOL__
#define HWEMUL_CLASS 0xfe
#define HWEMUL_SUBCLASS 0xac
#define HWEMUL_PROTOCOL 0x1d
#define HWEMUL_VERSION_MAJOR 2
#define HWEMUL_VERSION_MINOR 8
#define HWEMUL_VERSION_REV 2
#define HWEMUL_USB_VID 0xfee1
#define HWEMUL_USB_PID 0xdead
/**
* Control commands
*
* These commands are sent to the device, using the standard bRequest field
* of the SETUP packet. This is to take advantage of both wIndex and wValue
* although it would have been more correct to send them to the interface.
*/
/* list of commands */
#define HWEMUL_GET_INFO 0 /* mandatory */
#define HWEMUL_GET_LOG 1 /* optional */
#define HWEMUL_RW_MEM 2 /* optional */
#define HWEMUL_CALL 3 /* optional */
#define HWEMUL_JUMP 4 /* optional */
#define HWEMUL_AES_OTP 5 /* optional */
/**
* HWEMUL_GET_INFO: get some information about an aspect of the device.
* The wIndex field of the SETUP specifies which information to get. */
/* list of possible information */
#define HWEMUL_INFO_VERSION 0
#define HWEMUL_INFO_LAYOUT 1
#define HWEMUL_INFO_STMP 2
#define HWEMUL_INFO_FEATURES 3
struct usb_resp_info_version_t
{
uint8_t major;
uint8_t minor;
uint8_t revision;
} __attribute__((packed));
struct usb_resp_info_layout_t
{
/* describe the range of memory used by the running code */
uint32_t oc_code_start;
uint32_t oc_code_size;
/* describe the range of memory used by the stack */
uint32_t oc_stack_start;
uint32_t oc_stack_size;
/* describe the range of memory available as a buffer */
uint32_t oc_buffer_start;
uint32_t oc_buffer_size;
} __attribute__((packed));
struct usb_resp_info_stmp_t
{
uint16_t chipid; /* 0x3780 for STMP3780 for example */
uint8_t rev; /* 0=TA1 on STMP3780 for example */
uint8_t is_supported; /* 1 if the chip is supported */
} __attribute__((packed));
/* list of possible features */
#define HWEMUL_FEATURE_LOG (1 << 0)
#define HWEMUL_FEATURE_MEM (1 << 1)
#define HWEMUL_FEATURE_CALL (1 << 2)
#define HWEMUL_FEATURE_JUMP (1 << 2)
#define HWEMUL_FEATURE_AES_OTP (1 << 3)
struct usb_resp_info_features_t
{
uint32_t feature_mask;
};
/**
* HWEMUL_GET_LOG: only if has HWEMUL_FEATURE_LOG.
* The log is returned as part of the control transfer.
*/
/**
* HWEMUL_RW_MEM: only if has HWEMUL_FEATURE_MEM.
* The 32-bit address is split into two parts.
* The low 16-bit are stored in wValue and the upper
* 16-bit are stored in wIndex. Depending on the transfer direction,
* the transfer is either a read or a write. */
/**
* HWEMUL_x: only if has HWEMUL_FEATURE_x where x=CALL or JUMP.
* The 32-bit address is split into two parts.
* The low 16-bit are stored in wValue and the upper
* 16-bit are stored in wIndex. Depending on the transfer direction,
* the transfer is either a read or a write. */
/**
* HWEMUL_AES_OTP: only if has HWEMUL_FEATURE_AES_OTP.
* The control transfer contains the data to be en/decrypted and the data
* is sent back on the interrupt endpoint. The first 16-bytes of the data
* are interpreted as the IV. The output format is the same.
* The wValue field contains the parameters of the process. */
#define HWEMUL_AES_OTP_ENCRYPT (1 << 0)
#endif /* __HWEMUL_PROTOCOL__ */

View file

@ -0,0 +1,27 @@
CC=gcc
AR=ar
CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC
LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC
LIB=libhwemul.a
REGTOOLS=../../regtools
DESC=$(REGTOOLS)/desc
HWEMULGEN=$(REGTOOLS)/hwemulgen
HWEMULSOC_PREFIX=hwemul_soc
SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c
OBJ=$(SRC:.c=.o)
all: $(LIB) $(EXEC)
$(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h:
$(HWEMULGEN) $(DESC)/*.xml $(HWEMULSOC_PREFIX)
%.o: %.c $(HWEMULSOC_PREFIX).h
$(CC) $(CFLAGS) -c -o $@ $<
$(LIB): $(OBJ)
$(AR) rcs $@ $^
clean:
rm -rf $(OBJ) $(LIB) $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h

View file

@ -0,0 +1,175 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "hwemul.h"
#include "hwemul_soc.h"
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/* requires then ->handle field only */
int hwemul_probe(struct hwemul_device_t *dev)
{
libusb_device *mydev = libusb_get_device(dev->handle);
int config_id;
libusb_get_configuration(dev->handle, &config_id);
struct libusb_config_descriptor *config;
libusb_get_active_config_descriptor(mydev, &config);
const struct libusb_endpoint_descriptor *endp = NULL;
int intf;
for(intf = 0; intf < config->bNumInterfaces; intf++)
{
if(config->interface[intf].num_altsetting != 1)
continue;
const struct libusb_interface_descriptor *interface =
&config->interface[intf].altsetting[0];
if(interface->bNumEndpoints != 3 ||
interface->bInterfaceClass != HWEMUL_CLASS ||
interface->bInterfaceSubClass != HWEMUL_SUBCLASS ||
interface->bInterfaceProtocol != HWEMUL_PROTOCOL)
continue;
dev->intf = intf;
dev->bulk_in = dev->bulk_out = dev->int_in = -1;
for(int ep = 0; ep < interface->bNumEndpoints; ep++)
{
endp = &interface->endpoint[ep];
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
dev->int_in = endp->bEndpointAddress;
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
dev->bulk_in = endp->bEndpointAddress;
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
dev->bulk_out = endp->bEndpointAddress;
}
if(dev->bulk_in == -1 || dev->bulk_out == -1 || dev->int_in == -1)
continue;
break;
}
if(intf == config->bNumInterfaces)
return 1;
return libusb_claim_interface(dev->handle, intf);
}
int hwemul_release(struct hwemul_device_t *dev)
{
return libusb_release_interface(dev->handle, dev->intf);
}
int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
HWEMUL_GET_INFO, 0, idx, info, sz, 1000);
}
int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
HWEMUL_GET_LOG, 0, 0, buf, sz, 1000);
}
int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
{
size_t tot_sz = 0;
while(sz)
{
uint16_t xfer = MIN(1 * 1024, sz);
int ret = libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
(read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
HWEMUL_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
if(ret != xfer)
return ret;
sz -= xfer;
addr += xfer;
buf += xfer;
tot_sz += xfer;
}
return tot_sz;
}
int hwemul_call(struct hwemul_device_t *dev, uint32_t addr)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
LIBUSB_ENDPOINT_OUT, HWEMUL_CALL, addr & 0xffff, addr >> 16, NULL, 0,
1000);
}
int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr)
{
return libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
LIBUSB_ENDPOINT_OUT, HWEMUL_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
1000);
}
const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
{
switch(stmp->chipid)
{
case 0x3700: return "STMP 3700";
case 0x37b0: return "STMP 3770";
case 0x3780: return "STMP 3780 / i.MX233";
default: return "unknown";
}
}
const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
{
switch(stmp->chipid)
{
case 0x37b0:
case 0x3780:
switch(stmp->rev)
{
case 0: return "TA1";
case 1: return "TA2";
case 2: return "TA3";
case 3: return "TA4";
default: return "unknown";
}
break;
default:
return "unknown";
}
}
int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param)
{
int ret = libusb_control_transfer(dev->handle,
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
LIBUSB_ENDPOINT_OUT, HWEMUL_AES_OTP, param, 0, buf, sz,
1000);
if(ret <0 || (unsigned)ret != sz)
return -1;
int xfer;
ret = libusb_interrupt_transfer(dev->handle, dev->int_in, buf, sz, &xfer, 1000);
if(ret < 0 || (unsigned)xfer != sz)
return -1;
return ret;
}

View file

@ -0,0 +1,63 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __HWEMUL__
#define __HWEMUL__
#include <libusb.h>
#include "hwemul_protocol.h"
#include "hwemul_soc.h"
/**
*
* Low-Level interface
*
*/
struct hwemul_device_t
{
libusb_device_handle *handle;
int intf;
int bulk_in;
int bulk_out;
int int_in;
};
/* Requires then ->handle field only. Returns 0 on success */
int hwemul_probe(struct hwemul_device_t *dev);
/* Returns 0 on success */
int hwemul_release(struct hwemul_device_t *dev);
/* Returns number of bytes filled */
int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz);
/* Returns number of bytes filled */
int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz);
/* Returns number of bytes written/read or <0 on error */
int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
/* Returns <0 on error */
int hwemul_call(struct hwemul_device_t *dev, uint32_t addr);
int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr);
/* Returns <0 on error. The size must be a multiple of 16. */
int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param);
const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp);
const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp);
#endif /* __HWEMUL__ */

View file

@ -0,0 +1 @@
#include "../hwemul_protocol.h"

View file

@ -0,0 +1,22 @@
CC=gcc
AR=ar
HWEMUL_LIB_DIR=../lib
CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWEMUL_LIB_DIR)
LDFLAGS=`pkg-config --libs libusb-1.0`
EXEC=hwemul_tool
HWEMUL_LIB=$(HWEMUL_LIB_DIR)/libhwemul.a
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
all: $(EXEC)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
hwemul_tool: hwemul_tool.o $(HWEMUL_LIB)
$(CC) $(LDFLAGS) -o $@ $^
clean:
rm -rf $(OBJ) $(LIB)

Binary file not shown.

View file

@ -0,0 +1,558 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "hwemul.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
bool g_quiet = false;
struct hwemul_device_t hwdev;
struct hwemul_soc_t *cur_soc = NULL;
void print_log(struct hwemul_device_t *hwdev)
{
do
{
char buffer[128];
int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
if(length <= 0)
break;
buffer[length] = 0;
printf("%s", buffer);
}while(1);
}
int print_help()
{
printf("Commands:\n");
printf(" help\t\tDisplay this help\n");
printf(" call <addr>\tCall address <addr>\n");
printf(" quit\t\tQuit this session\n");
printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
printf(" read <regname>\tRead a register by name\n");
printf(" read <regname>.<field>\tRead a register field by name\n");
printf(" soc <socname>\tSelect the soc description to use\n");
printf(" write <value> <regname>\tWrite a register by name\n");
printf(" write <value <regname>.<field>\tWrite a register field by name\n");
printf(" NOTE: if the register is SCT variant, no read is performed.\n");
return 1;
}
int syntax_error(char *str)
{
printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
return 1;
}
int parse_uint32(char *str, uint32_t *u)
{
char *end;
*u = strtoul(str, &end, 0);
return *end == 0;
}
int do_call(uint32_t a)
{
hwemul_call(&hwdev, a);
return 1;
}
int parse_call()
{
char *arg = strtok(NULL, " ");
uint32_t addr;
if(arg && parse_uint32(arg, &addr))
return do_call(addr);
else
return syntax_error(arg);
}
int do_read32(uint32_t a)
{
uint32_t val;
if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
printf("%#x = %#x\n", a, val);
else
printf("read error at %#x\n", a);
return 1;
}
int parse_read32()
{
char *arg = strtok(NULL, " ");
uint32_t addr;
if(arg && parse_uint32(arg, &addr))
return do_read32(addr);
else
return syntax_error(arg);
}
int do_write32(uint32_t val, uint32_t a)
{
if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
printf("data written\n");
else
printf("write error at %#x\n", a);
return 1;
}
int parse_write32()
{
char *arg = strtok(NULL, " ");
uint32_t val;
if(!arg || !parse_uint32(arg, &val))
return syntax_error(arg);
uint32_t addr;
arg = strtok(NULL, " ");
if(arg && parse_uint32(arg, &addr))
return do_write32(val, addr);
else
return syntax_error(arg);
}
struct hwemul_soc_t *find_soc_by_name(const char *soc)
{
struct hwemul_soc_list_t *list = hwemul_get_soc_list();
for(size_t i = 0; i < list->nr_socs; i++)
if(strcmp(soc, list->socs[i]->name) == 0)
return list->socs[i];
return NULL;
}
struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
{
for(size_t i = 0; i < soc->nr_regs; i++)
if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
return soc->regs_by_name[i];
return NULL;
}
struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
{
for(size_t i = 0; i < reg->nr_fields; i++)
if(strcmp(field, reg->fields_by_name[i]->name) == 0)
return reg->fields_by_name[i];
return NULL;
}
int do_read(char *regname)
{
char *dot = strchr(regname, '.');
if(dot != NULL)
*dot++ = 0;
if(cur_soc == NULL)
{
printf("No soc selected!\n");
return 1;
}
struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
if(reg == NULL)
{
printf("no reg '%s' found\n", regname);
return 1;
}
uint32_t val;
if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
{
printf("read error at %#x\n", reg->addr);
return 1;
}
if(dot)
{
struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
if(field == NULL)
{
printf("no field '%s' found\n", dot);
return 1;
}
val >>= field->first_bit;
val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
printf("%s.%s = %#x\n", regname, dot, val);
}
else
printf("%s = %#x\n", regname, val);
return 1;
}
int parse_read()
{
char *arg = strtok(NULL, " ");
if(arg)
return do_read(arg);
else
return syntax_error(arg);
}
int do_soc(char *soc)
{
struct hwemul_soc_t *s = find_soc_by_name(soc);
if(s == NULL)
printf("no soc '%s' found\n", soc);
else
cur_soc = s;
return 1;
}
int parse_soc()
{
char *arg = strtok(NULL, " ");
if(arg)
return do_soc(arg);
else
return syntax_error(arg);
}
int do_write(uint32_t val, char *regname)
{
char *dot = strchr(regname, '.');
if(dot != NULL)
*dot++ = 0;
if(cur_soc == NULL)
{
printf("No soc selected!\n");
return 1;
}
struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
int is_sct = 0;
uint32_t addr_off = 0;
if(reg == NULL)
{
size_t len = strlen(regname);
/* try SCT variant */
if(strcmp(regname + len - 4, "_SET") == 0)
addr_off = 4;
else if(strcmp(regname + len - 4, "_CLR") == 0)
addr_off = 8;
else if(strcmp(regname + len - 4, "_TOG") == 0)
addr_off = 12;
else
{
printf("no reg '%s' found\n", regname);
return 1;
}
is_sct = 1;
regname[len - 4] = 0;
reg = find_reg_by_name(cur_soc, regname);
if(reg == NULL)
{
printf("no reg '%s' found\n", regname);
return 1;
}
}
if(dot)
{
struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
if(field == NULL)
{
printf("no field '%s' found\n", dot);
return 1;
}
uint32_t actual_val = 0;
if(!is_sct)
{
if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
{
printf("read error at %#x\n", reg->addr);
return 1;
}
printf("read %#x at %#x\n", actual_val, reg->addr);
}
uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
printf("mask=%#x\n", mask);
val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
}
printf("write %#x to %#x\n", val, reg->addr + addr_off);
if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
{
printf("write error at %#x\n", reg->addr);
return 1;
}
return 1;
}
int parse_write()
{
char *arg = strtok(NULL, " ");
uint32_t val;
if(!arg || !parse_uint32(arg, &val))
return syntax_error(arg);
arg = strtok(NULL, " ");
if(arg)
return do_write(val, arg);
else
return syntax_error(arg);
}
int parse_command(char *cmd)
{
if(strcmp(cmd, "help") == 0)
return print_help();
if(strcmp(cmd, "quit") == 0)
return 0;
if(strcmp(cmd, "call") == 0)
return parse_call();
if(strcmp(cmd, "read32") == 0)
return parse_read32();
if(strcmp(cmd, "write32") == 0)
return parse_write32();
if(strcmp(cmd, "read") == 0)
return parse_read();
if(strcmp(cmd, "soc") == 0)
return parse_soc();
if(strcmp(cmd, "write") == 0)
return parse_write();
return syntax_error(cmd);
}
int do_command()
{
char *line = NULL;
int size = 0;
getline(&line, &size, stdin);
char *end = strchr(line, '\n');
if(end)
*end = 0;
char *pch = strtok(line, " ");
int ret;
if(pch)
ret = parse_command(pch);
else
ret = print_help();
free(line);
return ret;
}
void usage(void)
{
printf("hwemul_tool, compiled with hwemul %d.%d.%d\n",
HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, HWEMUL_VERSION_REV);
printf("available soc descriptions:");
for(unsigned i = 0; i < hwemul_get_soc_list()->nr_socs; i++)
printf(" %s", hwemul_get_soc_list()->socs[i]->name);
printf("\n");
printf("usage: hwemul_tool [options]\n");
printf("options:\n");
printf(" --help/-?\tDisplay this help\n");
printf(" --quiet/-q\tQuiet non-command messages\n");
exit(1);
}
int main(int argc, char **argv)
{
while(1)
{
static struct option long_options[] =
{
{"help", no_argument, 0, '?'},
{"quiet", no_argument, 0, 'q'},
{0, 0, 0, 0}
};
int c = getopt_long(argc, argv, "?q", long_options, NULL);
if(c == -1)
break;
switch(c)
{
case -1:
break;
case 'q':
g_quiet = true;
break;
case '?':
usage();
break;
default:
abort();
}
}
if(argc - optind != 0)
{
usage();
return 1;
}
libusb_context *ctx;
libusb_init(&ctx);
libusb_set_debug(ctx, 3);
if(!g_quiet)
printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID, HWEMUL_USB_PID);
libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
HWEMUL_USB_VID, HWEMUL_USB_PID);
if(handle == NULL)
{
printf("No device found\n");
return 1;
}
libusb_device *mydev = libusb_get_device(handle);
if(!g_quiet)
{
printf("device found at %d:%d\n",
libusb_get_bus_number(mydev),
libusb_get_device_address(mydev));
}
hwdev.handle = handle;
if(hwemul_probe(&hwdev))
{
printf("Cannot probe device!\n");
return 1;
}
struct usb_resp_info_version_t ver;
int ret = hwemul_get_info(&hwdev, HWEMUL_INFO_VERSION, &ver, sizeof(ver));
if(ret != sizeof(ver))
{
printf("Cannot get version!\n");
goto Lerr;
}
if(!g_quiet)
printf("Device version: %d.%d.%d\n", ver.major, ver.minor, ver.revision);
struct usb_resp_info_layout_t layout;
ret = hwemul_get_info(&hwdev, HWEMUL_INFO_LAYOUT, &layout, sizeof(layout));
if(ret != sizeof(layout))
{
printf("Cannot get layout: %d\n", ret);
goto Lerr;
}
if(!g_quiet)
{
printf("Device layout:\n");
printf(" Code: 0x%x (0x%x)\n", layout.oc_code_start, layout.oc_code_size);
printf(" Stack: 0x%x (0x%x)\n", layout.oc_stack_start, layout.oc_stack_size);
printf(" Buffer: 0x%x (0x%x)\n", layout.oc_buffer_start, layout.oc_buffer_size);
}
struct usb_resp_info_features_t features;
ret = hwemul_get_info(&hwdev, HWEMUL_INFO_FEATURES, &features, sizeof(features));
if(ret != sizeof(features))
{
printf("Cannot get features: %d\n", ret);
goto Lerr;
}
if(!g_quiet)
{
printf("Device features:");
if(features.feature_mask & HWEMUL_FEATURE_LOG)
printf(" log");
if(features.feature_mask & HWEMUL_FEATURE_MEM)
printf(" mem");
if(features.feature_mask & HWEMUL_FEATURE_CALL)
printf(" call");
if(features.feature_mask & HWEMUL_FEATURE_JUMP)
printf(" jump");
if(features.feature_mask & HWEMUL_FEATURE_AES_OTP)
printf(" aes_otp");
printf("\n");
}
struct usb_resp_info_stmp_t stmp;
ret = hwemul_get_info(&hwdev, HWEMUL_INFO_STMP, &stmp, sizeof(stmp));
if(ret != sizeof(stmp))
{
printf("Cannot get stmp: %d\n", ret);
goto Lerr;
}
if(!g_quiet)
{
printf("Device stmp:\n");
printf(" chip ID: %x (%s)\n", stmp.chipid,hwemul_get_product_string(&stmp));
printf(" revision: %d (%s)\n", stmp.rev, hwemul_get_rev_string(&stmp));
printf(" supported: %d\n", stmp.is_supported);
}
if(!g_quiet)
{
void *rom = malloc(64 * 1024);
ret = hwemul_rw_mem(&hwdev, 1, 0xc0000000, rom, 64 * 1024);
if(ret != 64 * 1024)
{
printf("Cannot read ROM: %d\n", ret);
goto Lerr;
}
printf("ROM successfully read!\n");
FILE *f = fopen("rom.bin", "wb");
fwrite(rom, 64 * 1024, 1, f);
fclose(f);
}
if(!g_quiet)
{
struct
{
uint8_t iv[16];
uint8_t data[16];
} __attribute__((packed)) dcp_test;
for(int i = 0; i < 16; i++)
dcp_test.iv[i] = rand();
for(int i = 0; i < 16; i++)
dcp_test.data[i] = rand();
printf("DCP\n");
printf(" IN\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.iv[i]);
printf("\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.data[i]);
printf("\n");
if(!hwemul_aes_otp(&hwdev, &dcp_test, sizeof(dcp_test), HWEMUL_AES_OTP_ENCRYPT))
{
printf(" OUT\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.iv[i]);
printf("\n");
printf(" IV:");
for(int i = 0; i < 16; i++)
printf(" %02x", dcp_test.data[i]);
printf("\n");
}
else
printf("DCP error!\n");
}
if(!g_quiet)
printf("Starting interactive session. Type 'help' to get help.\n");
while(1)
if(!do_command())
break;
Lerr:
if(features.feature_mask & HWEMUL_FEATURE_LOG)
{
if(!g_quiet)
printf("Device log:\n");
print_log(&hwdev);
}
hwemul_release(&hwdev);
return 1;
}