summaryrefslogtreecommitdiff
path: root/utils/imxtools/sbtools
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-05-23 11:03:35 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-05-31 13:57:25 +0200
commita87a9ef37372b4380808ec2efa7c762e137668f1 (patch)
tree9c759088f0f9cf6717d96789b6805812f6b187ea /utils/imxtools/sbtools
parentba8e4367fb4d116ffc01c12cc619bfc714e582c9 (diff)
downloadrockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.tar.gz
rockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.zip
imxtools: move tools to a new sbtools/ subdirectory
Change-Id: I0d8d6831b35037725486f61fc363de87bc8ba92e
Diffstat (limited to 'utils/imxtools/sbtools')
-rw-r--r--utils/imxtools/sbtools/Makefile26
-rw-r--r--utils/imxtools/sbtools/README32
-rw-r--r--utils/imxtools/sbtools/aes128.c284
-rw-r--r--utils/imxtools/sbtools/crc.c83
-rw-r--r--utils/imxtools/sbtools/crypto.c188
-rw-r--r--utils/imxtools/sbtools/crypto.h115
-rw-r--r--utils/imxtools/sbtools/dbparser.c857
-rw-r--r--utils/imxtools/sbtools/dbparser.h118
-rw-r--r--utils/imxtools/sbtools/elf.c575
-rw-r--r--utils/imxtools/sbtools/elf.h94
-rw-r--r--utils/imxtools/sbtools/elftosb.c462
-rw-r--r--utils/imxtools/sbtools/fuze+_key_file.txt1
-rw-r--r--utils/imxtools/sbtools/misc.c265
-rw-r--r--utils/imxtools/sbtools/misc.h59
-rw-r--r--utils/imxtools/sbtools/sb.c1224
-rw-r--r--utils/imxtools/sbtools/sb.h243
-rw-r--r--utils/imxtools/sbtools/sbloader.c193
-rw-r--r--utils/imxtools/sbtools/sbtoelf.c303
-rw-r--r--utils/imxtools/sbtools/sha1.c150
19 files changed, 5272 insertions, 0 deletions
diff --git a/utils/imxtools/sbtools/Makefile b/utils/imxtools/sbtools/Makefile
new file mode 100644
index 0000000000..7a09d86d24
--- /dev/null
+++ b/utils/imxtools/sbtools/Makefile
@@ -0,0 +1,26 @@
1DEFINES=-DCRYPTO_LIBUSB
2CC=gcc
3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
5LDFLAGS=`pkg-config --libs libusb-1.0`
6BINS=elftosb sbtoelf sbloader
7
8all: $(BINS)
9
10%.o: %.c
11 $(CC) $(CFLAGS) -c -o $@ $<
12
13sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o
14 $(LD) -o $@ $^ $(LDFLAGS)
15
16elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
17 $(LD) -o $@ $^ $(LDFLAGS)
18
19sbloader: sbloader.o
20 $(LD) -o $@ $^ $(LDFLAGS)
21
22clean:
23 rm -fr *.o
24
25veryclean:
26 rm -rf $(BINS)
diff --git a/utils/imxtools/sbtools/README b/utils/imxtools/sbtools/README
new file mode 100644
index 0000000000..8bf6fd5f8e
--- /dev/null
+++ b/utils/imxtools/sbtools/README
@@ -0,0 +1,32 @@
1This file document the format of the command file used by the elftosb tool.
2By no way our tools tries to be compatible with Freescale's elftosb2.
3However, our format is more subset of the general one.
4
5The parse supports a limited form of comments: comments starting with // and ending at the end of the line.
6
7A file first contains the list of sources:
8
9sources
10{
11 hw_init = "sdram_init.elf";
12 rockbox = "rockbox.elf";
13}
14
15It can then contain an arbitrary number of section. A section is identified by a number.
16Within a section, three commands are supported: "load", "jump" and "call":
17
18section(0x626f6f74) // hex for 'boot'
19{
20 load hw_init;
21 call hw_init;
22 load rockbox;
23 jump rockbox;
24}
25
26Finally, both elftosb and sbtoelf tools use key files. A key file is a list of keys.
27Each key consist is 128-bit long and is written in hexadecimal:
28
2900000000000000000000000000000000
30
31The parser does not handle blank line and only allows a final newline at the end of the file.
32A file is allowed to contain zero (0) keys.
diff --git a/utils/imxtools/sbtools/aes128.c b/utils/imxtools/sbtools/aes128.c
new file mode 100644
index 0000000000..5870813db8
--- /dev/null
+++ b/utils/imxtools/sbtools/aes128.c
@@ -0,0 +1,284 @@
1// Simple, thoroughly commented implementation of 128-bit AES / Rijndael using C
2// Chris Hulbert - chris.hulbert@gmail.com - http://splinter.com.au/blog
3// References:
4// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
5// http://en.wikipedia.org/wiki/Rijndael_key_schedule
6// http://en.wikipeia.org/wiki/Rijndael_mix_columns
7// http://en.wikipedia.org/wiki/Rijndael_S-box
8// This code is public domain, or any OSI-approved license, your choice. No warranty.
9#include "crypto.h"
10
11// Here are all the lookup tables for the row shifts, rcon, s-boxes, and galois field multiplications
12byte shift_rows_table[] = {0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11};
13byte shift_rows_table_inv[] = {0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3};
14byte lookup_rcon[]={0x8d,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a};
15byte lookup_sbox[]={0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16};
16byte lookup_sbox_inv[]={0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d};
17byte lookup_g2 []={0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05,0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25,0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45,0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65,0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85,0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5,0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5,0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5};
18byte lookup_g3 []={0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11,0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21,0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71,0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41,0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1,0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1,0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1,0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81,0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a,0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba,0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea,0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda,0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a,0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a,0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a,0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a};
19byte lookup_g9 []={0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7,0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc,0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01,0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91,0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a,0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa,0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b,0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b,0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0,0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30,0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed,0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d,0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6,0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46};
20byte lookup_g11 []={0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69,0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9,0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12,0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2,0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f,0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f,0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4,0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54,0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e,0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e,0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5,0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55,0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68,0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8,0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13,0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3};
21byte lookup_g13 []={0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b,0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b,0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0,0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20,0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26,0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6,0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d,0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d,0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91,0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41,0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a,0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa,0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc,0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c,0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47,0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97};
22byte lookup_g14 []={0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a,0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba,0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81,0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61,0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7,0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17,0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c,0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc,0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b,0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb,0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0,0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20,0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6,0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56,0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d,0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d};
23
24// Xor's all elements in a n byte array a by b
25void xor_(byte *a, byte *b, int n) {
26 int i;
27 for (i=0;i<n;i++)
28 a[i] ^= b[i];
29}
30
31// Xor the current cipher state by a specific round key
32static void xor_round_key(byte *state, byte *keys, int round) {
33 xor_(state,keys+round*16,16);
34}
35
36// Apply and reverse the rijndael s-box to all elements in an array
37// http://en.wikipedia.org/wiki/Rijndael_S-box
38static void sub_bytes(byte *a,int n) {
39 int i;
40 for (i=0;i<n;i++)
41 a[i] = lookup_sbox[a[i]];
42}
43static void sub_bytes_inv(byte *a,int n) {
44 int i;
45 for (i=0;i<n;i++)
46 a[i] = lookup_sbox_inv[a[i]];
47}
48
49// Perform the core key schedule transform on 4 bytes, as part of the key expansion process
50// http://en.wikipedia.org/wiki/Rijndael_key_schedule#Key_schedule_core
51static void key_schedule_core(byte *a, int i) {
52 byte temp = a[0]; // Rotate the output eight bits to the left
53 a[0]=a[1];
54 a[1]=a[2];
55 a[2]=a[3];
56 a[3]=temp;
57 sub_bytes(a,4); // Apply Rijndael's S-box on all four individual bytes in the output word
58 a[0]^=lookup_rcon[i]; // On just the first (leftmost) byte of the output word, perform the rcon operation with i
59 // as the input, and exclusive or the rcon output with the first byte of the output word
60}
61
62// Expand the 16-byte key to 11 round keys (176 bytes)
63// http://en.wikipedia.org/wiki/Rijndael_key_schedule#The_key_schedule
64static void expand_key(byte *key, byte *keys) {
65 int bytes=16; // The count of how many bytes we've created so far
66 int i=1; // The rcon iteration value i is set to 1
67 int j; // For repeating the second stage 3 times
68 byte t[4]; // Temporary working area known as 't' in the Wiki article
69 memcpy(keys,key,16); // The first 16 bytes of the expanded key are simply the encryption key
70
71 while (bytes<176) { // Until we have 176 bytes of expanded key, we do the following:
72 memcpy(t,keys+bytes-4,4); // We assign the value of the previous four bytes in the expanded key to t
73 key_schedule_core(t, i); // We perform the key schedule core on t, with i as the rcon iteration value
74 i++; // We increment i by 1
75 xor_(t,keys+bytes-16,4); // We exclusive-or t with the four-byte block 16 bytes before the new expanded key.
76 memcpy(keys+bytes,t,4); // This becomes the next 4 bytes in the expanded key
77 bytes+=4; // Keep track of how many expanded key bytes we've added
78
79 // We then do the following three times to create the next twelve bytes
80 for (j=0;j<3;j++) {
81 memcpy(t,keys+bytes-4,4); // We assign the value of the previous 4 bytes in the expanded key to t
82 xor_(t,keys+bytes-16,4); // We exclusive-or t with the four-byte block n bytes before
83 memcpy(keys+bytes,t,4); // This becomes the next 4 bytes in the expanded key
84 bytes+=4; // Keep track of how many expanded key bytes we've added
85 }
86 }
87}
88
89// Apply / reverse the shift rows step on the 16 byte cipher state
90// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_ShiftRows_step
91static void shift_rows(byte *state) {
92 int i;
93 byte temp[16];
94 memcpy(temp,state,16);
95 for (i=0;i<16;i++)
96 state[i]=temp[shift_rows_table[i]];
97}
98static void shift_rows_inv(byte *state) {
99 int i;
100 byte temp[16];
101 memcpy(temp,state,16);
102 for (i=0;i<16;i++)
103 state[i]=temp[shift_rows_table_inv[i]];
104}
105
106// Perform the mix columns matrix on one column of 4 bytes
107// http://en.wikipedia.org/wiki/Rijndael_mix_columns
108static void mix_col (byte *state) {
109 byte a0 = state[0];
110 byte a1 = state[1];
111 byte a2 = state[2];
112 byte a3 = state[3];
113 state[0] = lookup_g2[a0] ^ lookup_g3[a1] ^ a2 ^ a3;
114 state[1] = lookup_g2[a1] ^ lookup_g3[a2] ^ a3 ^ a0;
115 state[2] = lookup_g2[a2] ^ lookup_g3[a3] ^ a0 ^ a1;
116 state[3] = lookup_g2[a3] ^ lookup_g3[a0] ^ a1 ^ a2;
117}
118
119// Perform the mix columns matrix on each column of the 16 bytes
120static void mix_cols (byte *state) {
121 mix_col(state);
122 mix_col(state+4);
123 mix_col(state+8);
124 mix_col(state+12);
125}
126
127// Perform the inverse mix columns matrix on one column of 4 bytes
128// http://en.wikipedia.org/wiki/Rijndael_mix_columns
129static void mix_col_inv (byte *state) {
130 byte a0 = state[0];
131 byte a1 = state[1];
132 byte a2 = state[2];
133 byte a3 = state[3];
134 state[0] = lookup_g14[a0] ^ lookup_g9[a3] ^ lookup_g13[a2] ^ lookup_g11[a1];
135 state[1] = lookup_g14[a1] ^ lookup_g9[a0] ^ lookup_g13[a3] ^ lookup_g11[a2];
136 state[2] = lookup_g14[a2] ^ lookup_g9[a1] ^ lookup_g13[a0] ^ lookup_g11[a3];
137 state[3] = lookup_g14[a3] ^ lookup_g9[a2] ^ lookup_g13[a1] ^ lookup_g11[a0];
138}
139
140// Perform the inverse mix columns matrix on each column of the 16 bytes
141static void mix_cols_inv (byte *state) {
142 mix_col_inv(state);
143 mix_col_inv(state+4);
144 mix_col_inv(state+8);
145 mix_col_inv(state+12);
146}
147
148// Encrypt a single 128 bit block by a 128 bit key using AES
149// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
150void EncryptAES(byte *msg, byte *key, byte *c) {
151 int i; // To count the rounds
152
153 // Key expansion
154 byte keys[176];
155 expand_key(key,keys);
156
157 // First Round
158 memmove(c, msg, 16);
159 xor_round_key(c,keys,0);
160
161 // Middle rounds
162 for(i=0; i<9; i++) {
163 sub_bytes(c,16);
164 shift_rows(c);
165 mix_cols(c);
166 xor_round_key(c, keys, i+1);
167 }
168
169 // Final Round
170 sub_bytes(c,16);
171 shift_rows(c);
172 xor_round_key(c, keys, 10);
173}
174
175// Decrypt a single 128 bit block by a 128 bit key using AES
176// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
177void DecryptAES(byte *c, byte *key, byte *m) {
178 int i; // To count the rounds
179
180 // Key expansion
181 byte keys[176];
182 expand_key(key,keys);
183
184 // Reverse the final Round
185 memcpy(m,c,16);
186 xor_round_key(m,keys,10);
187 shift_rows_inv(m);
188 sub_bytes_inv(m, 16);
189
190 // Reverse the middle rounds
191 for (i=0; i<9; i++) {
192 xor_round_key(m,keys,9-i);
193 mix_cols_inv(m);
194 shift_rows_inv(m);
195 sub_bytes_inv(m, 16);
196 }
197
198 // Reverse the first Round
199 xor_round_key(m, keys, 0);
200}
201
202/*
203// Pretty-print a key (or any smallish buffer) onto screen as hex
204void Pretty(byte* b,int len,const char* label)
205{
206 char out[100];
207 int i;
208 for (i=0;i<len;i++)
209 sprintf(out+i*2,"%02x",b[i]);
210
211 printf("%s%s",label, out);
212}
213*/
214
215/*
216// Test AES
217int main(void)
218{
219 byte key[] = {0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12};
220 byte msg[] = {0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab};
221 byte encrypted[16], decrypted[16];
222
223 printf("Test AES\r\n\n");
224 Pretty(key,16,"Key: ");
225 Pretty(msg,16,"Original: ");
226
227 EncryptAES(msg,key,encrypted);
228 printf("Encrypted should be: 85E5A3D7356A61E29A8AFA559AD67102\r\n");
229 Pretty(encrypted,16,"Encrypted: ");
230
231 DecryptAES(encrypted,key,decrypted);
232 Pretty(decrypted,16,"Decrypted: ");
233
234 return 0;
235}
236*/
237
238void cbc_mac(
239 byte *in_data, /* Input data */
240 byte *out_data, /* Output data (or NULL) */
241 int nr_blocks, /* Number of blocks to encrypt/decrypt (one block=16 bytes) */
242 byte key[16], /* Key */
243 byte iv[16], /* Initialisation Vector */
244 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
245 int encrypt /* 1 to encrypt, 0 to decrypt */
246 )
247{
248 byte feedback[16];
249 memcpy(feedback, iv, 16);
250
251 if(encrypt)
252 {
253 /* for each block */
254 for(int i = 0; i < nr_blocks; i++)
255 {
256 /* xor it with feedback */
257 xor_(feedback, &in_data[i * 16], 16);
258 /* encrypt it using aes */
259 EncryptAES(feedback, key, feedback);
260 /* write cipher to output */
261 if(out_data)
262 memcpy(&out_data[i * 16], feedback, 16);
263 }
264 if(out_cbc_mac)
265 memcpy(out_cbc_mac, feedback, 16);
266 }
267 else
268 {
269 /* nothing to do ? */
270 if(out_data == NULL)
271 return;
272
273 /* for each block */
274 for(int i = 0; i < nr_blocks; i++)
275 {
276 /* decrypt it using aes */
277 DecryptAES(&in_data[i * 16], key, &out_data[i * 16]);
278 /* xor it with iv */
279 xor_(&out_data[i * 16], feedback, 16);
280 /* copy cipher to iv */
281 memcpy(feedback, &in_data[i * 16], 16);
282 }
283 }
284}
diff --git a/utils/imxtools/sbtools/crc.c b/utils/imxtools/sbtools/crc.c
new file mode 100644
index 0000000000..eaf257ddfe
--- /dev/null
+++ b/utils/imxtools/sbtools/crc.c
@@ -0,0 +1,83 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 "crypto.h"
22
23/* Table extracted from firmware, don't know if this is regular CRC32 */
24
25static uint32_t crc_table[256] = {
26 0x0, 0x4C11DB7, 0x9823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2,
27 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64,
28 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E,
29 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8,
30 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
31 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C,
32 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0x0BE2B5B58, 0x0BAEA46EF, 0x0B7A96036,
33 0x0B3687D81, 0x0AD2F2D84, 0x0A9EE3033, 0x0A4AD16EA, 0x0A06C0B5D, 0x0D4326D90,
34 0x0D0F37027, 0x0DDB056FE, 0x0D9714B49, 0x0C7361B4C, 0x0C3F706FB, 0x0CEB42022,
35 0x0CA753D95, 0x0F23A8028, 0x0F6FB9D9F, 0x0FBB8BB46, 0x0FF79A6F1, 0x0E13EF6F4,
36 0x0E5FFEB43, 0x0E8BCCD9A, 0x0EC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19,
37 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF,
38 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x18AEB13, 0x54BF6A4, 0x808D07D,
39 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB,
40 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
41 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0x0ACA5C697,
42 0x0A864DB20, 0x0A527FDF9, 0x0A1E6E04E, 0x0BFA1B04B, 0x0BB60ADFC, 0x0B6238B25,
43 0x0B2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3,
44 0x9D684044, 0x902B669D, 0x94EA7B2A, 0x0E0B41DE7, 0x0E4750050, 0x0E9362689,
45 0x0EDF73B3E, 0x0F3B06B3B, 0x0F771768C, 0x0FA325055, 0x0FEF34DE2, 0x0C6BCF05F,
46 0x0C27DEDE8, 0x0CF3ECB31, 0x0CBFFD686, 0x0D5B88683, 0x0D1799B34, 0x0DC3ABDED,
47 0x0D8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632,
48 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638,
49 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E,
50 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
51 0x3B5A6B9B, 0x315D626, 0x7D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA,
52 0x14D0BD4D, 0x19939B94, 0x1D528623, 0x0F12F560E, 0x0F5EE4BB9, 0x0F8AD6D60,
53 0x0FC6C70D7, 0x0E22B20D2, 0x0E6EA3D65, 0x0EBA91BBC, 0x0EF68060B, 0x0D727BBB6,
54 0x0D3E6A601, 0x0DEA580D8, 0x0DA649D6F, 0x0C423CD6A, 0x0C0E2D0DD, 0x0CDA1F604,
55 0x0C960EBB3, 0x0BD3E8D7E, 0x0B9FF90C9, 0x0B4BCB610, 0x0B07DABA7, 0x0AE3AFBA2,
56 0x0AAFBE615, 0x0A7B8C0CC, 0x0A379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8,
57 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099,
58 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B,
59 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD,
60 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
61 0x1CD86D30, 0x29F3D35, 0x65E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651,
62 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3,
63 0x29D4F654, 0x0C5A92679, 0x0C1683BCE, 0x0CC2B1D17, 0x0C8EA00A0, 0x0D6AD50A5,
64 0x0D26C4D12, 0x0DF2F6BCB, 0x0DBEE767C, 0x0E3A1CBC1, 0x0E760D676, 0x0EA23F0AF,
65 0x0EEE2ED18, 0x0F0A5BD1D, 0x0F464A0AA, 0x0F9278673, 0x0FDE69BC4, 0x89B8FD09,
66 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB,
67 0x97FFAD0C, 0x0AFB010B1, 0x0AB710D06, 0x0A6322BDF, 0x0A2F33668, 0x0BCB4666D,
68 0x0B8757BDA, 0x0B5365D03, 0x0B1F740B4
69};
70
71uint32_t crc(byte *data, int size)
72{
73 return crc_continue(0xffffffff, data, size);
74}
75
76uint32_t crc_continue(uint32_t previous_crc, byte *data, int size)
77{
78 uint32_t c = previous_crc;
79 /* normal CRC */
80 for(int i = 0; i < size; i++)
81 c = crc_table[data[i] ^ (c >> 24)] ^ (c << 8);
82 return c;
83}
diff --git a/utils/imxtools/sbtools/crypto.c b/utils/imxtools/sbtools/crypto.c
new file mode 100644
index 0000000000..d4afc6c816
--- /dev/null
+++ b/utils/imxtools/sbtools/crypto.c
@@ -0,0 +1,188 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 "crypto.h"
22#include <stdio.h>
23#include <stdbool.h>
24#ifdef CRYPTO_LIBUSB
25#include "libusb.h"
26#endif
27#include "misc.h"
28
29static enum crypto_method_t cur_method = CRYPTO_NONE;
30static byte key[16];
31static uint16_t usb_vid, usb_pid;
32
33void crypto_setup(enum crypto_method_t method, void *param)
34{
35 cur_method = method;
36 switch(method)
37 {
38 case CRYPTO_KEY:
39 memcpy(key, param, sizeof(key));
40 break;
41 case CRYPTO_USBOTP:
42 {
43 uint32_t value = *(uint32_t *)param;
44 usb_vid = value >> 16;
45 usb_pid = value & 0xffff;
46 break;
47 }
48 default:
49 break;
50 }
51}
52
53int crypto_apply(
54 byte *in_data, /* Input data */
55 byte *out_data, /* Output data (or NULL) */
56 int nr_blocks, /* Number of blocks (one block=16 bytes) */
57 byte iv[16], /* Key */
58 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
59 int encrypt)
60{
61 if(cur_method == CRYPTO_KEY)
62 {
63 cbc_mac(in_data, out_data, nr_blocks, key, iv, out_cbc_mac, encrypt);
64 return CRYPTO_ERROR_SUCCESS;
65 }
66 #ifdef CRYPTO_LIBUSB
67 else if(cur_method == CRYPTO_USBOTP)
68 {
69 if(out_cbc_mac && !encrypt)
70 memcpy(*out_cbc_mac, in_data + 16 * (nr_blocks - 1), 16);
71
72 libusb_device_handle *handle = NULL;
73 libusb_context *ctx;
74 /* init library */
75 libusb_init(&ctx);
76 libusb_set_debug(NULL,3);
77 /* open device */
78 handle = libusb_open_device_with_vid_pid(ctx, usb_vid, usb_pid);
79 if(handle == NULL)
80 {
81 printf("usbotp: cannot open device %04x:%04x\n", usb_vid, usb_pid);
82 return CRYPTO_ERROR_NODEVICE;
83 }
84 /* get device pointer */
85 libusb_device *mydev = libusb_get_device(handle);
86 if(g_debug)
87 printf("usbotp: device found at %d:%d\n", libusb_get_bus_number(mydev),
88 libusb_get_device_address(mydev));
89 int config_id;
90 /* explore configuration */
91 libusb_get_configuration(handle, &config_id);
92 struct libusb_config_descriptor *config;
93 libusb_get_active_config_descriptor(mydev, &config);
94
95 if(g_debug)
96 {
97 printf("usbotp: configuration: %d\n", config_id);
98 printf("usbotp: interfaces: %d\n", config->bNumInterfaces);
99 }
100
101 const struct libusb_endpoint_descriptor *endp = NULL;
102 int intf, intf_alt;
103 for(intf = 0; intf < config->bNumInterfaces; intf++)
104 for(intf_alt = 0; intf_alt < config->interface[intf].num_altsetting; intf_alt++)
105 for(int ep = 0; ep < config->interface[intf].altsetting[intf_alt].bNumEndpoints; ep++)
106 {
107 endp = &config->interface[intf].altsetting[intf_alt].endpoint[ep];
108 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
109 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
110 goto Lfound;
111 }
112 libusb_close(handle);
113 printf("usbotp: No suitable endpoint found\n");
114 return CRYPTO_ERROR_BADENDP;
115
116 if(g_debug)
117 {
118 printf("usbotp: use interface %d, alt %d\n", intf, intf_alt);
119 printf("usbotp: use endpoint %d\n", endp->bEndpointAddress);
120 }
121 Lfound:
122 if(libusb_claim_interface(handle, intf) != 0)
123 {
124 if(g_debug)
125 printf("usbotp: claim error\n");
126 return CRYPTO_ERROR_CLAIMFAIL;
127 }
128
129 int buffer_size = 16 + 16 * nr_blocks;
130 unsigned char *buffer = xmalloc(buffer_size);
131 memcpy(buffer, iv, 16);
132 memcpy(buffer + 16, in_data, 16 * nr_blocks);
133 int ret = libusb_control_transfer(handle,
134 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE,
135 0xaa, encrypt ? 0xeeee : 0xdddd, 0, buffer, buffer_size, 1000);
136 if(ret < 0)
137 {
138 if(g_debug)
139 printf("usbotp: control transfer failed: %d\n", ret);
140 libusb_release_interface(handle, intf);
141 libusb_close(handle);
142 return CRYPTO_ERROR_DEVREJECT;
143 }
144
145 int recv_size;
146 ret = libusb_interrupt_transfer(handle, endp->bEndpointAddress, buffer,
147 buffer_size, &recv_size, 1000);
148 libusb_release_interface(handle, intf);
149 libusb_close(handle);
150
151 if(ret < 0)
152 {
153 if(g_debug)
154 printf("usbotp: interrupt transfer failed: %d\n", ret);
155 return CRYPTO_ERROR_DEVSILENT;
156 }
157 if(recv_size != buffer_size)
158 {
159 if(g_debug)
160 printf("usbotp: device returned %d bytes, expected %d\n", recv_size,
161 buffer_size);
162 return CRYPTO_ERROR_DEVERR;
163 }
164
165 if(out_data)
166 memcpy(out_data, buffer + 16, 16 * nr_blocks);
167 if(out_cbc_mac && encrypt)
168 memcpy(*out_cbc_mac, buffer + buffer_size - 16, 16);
169
170 return CRYPTO_ERROR_SUCCESS;
171 }
172 #endif
173 else
174 return CRYPTO_ERROR_BADSETUP;
175}
176
177int crypto_cbc(
178 byte *in_data, /* Input data */
179 byte *out_data, /* Output data (or NULL) */
180 int nr_blocks, /* Number of blocks (one block=16 bytes) */
181 struct crypto_key_t *key, /* Key */
182 byte iv[16], /* IV */
183 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
184 int encrypt)
185{
186 crypto_setup(key->method, (void *)key->u.param);
187 return crypto_apply(in_data, out_data, nr_blocks, iv, out_cbc_mac, encrypt);
188}
diff --git a/utils/imxtools/sbtools/crypto.h b/utils/imxtools/sbtools/crypto.h
new file mode 100644
index 0000000000..452db6a28d
--- /dev/null
+++ b/utils/imxtools/sbtools/crypto.h
@@ -0,0 +1,115 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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#ifndef __CRYPTO_H__
22#define __CRYPTO_H__
23
24#include <stdio.h>
25#include <stdint.h>
26#include <string.h>
27
28typedef uint8_t byte;
29
30/* aes128.c */
31void xor_(byte *a, byte *b, int n);
32void EncryptAES(byte *msg, byte *key, byte *c);
33void DecryptAES(byte *c, byte *key, byte *m);
34void Pretty(byte* b,int len,const char* label);
35void cbc_mac(
36 byte *in_data, /* Input data */
37 byte *out_data, /* Output data (or NULL) */
38 int nr_blocks, /* Number of blocks to encrypt/decrypt (one block=16 bytes) */
39 byte key[16], /* Key */
40 byte iv[16], /* Initialisation Vector */
41 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
42 int encrypt /* 1 to encrypt, 0 to decrypt */
43 );
44
45/* crypto.c */
46enum crypto_method_t
47{
48 CRYPTO_NONE, /* disable */
49 CRYPTO_KEY, /* key */
50 CRYPTO_USBOTP, /* use usbotp device */
51};
52
53/* parameter can be:
54 * - CRYPTO_KEY: array of 16-bytes (the key)
55 * - CRYPTO_USBOTP: 32-bit integer: vid << 16 | pid */
56void crypto_setup(enum crypto_method_t method, void *param);
57
58#define CRYPTO_ERROR_SUCCESS 0
59#define CRYPTO_ERROR_BADSETUP -1 /* bad crypto setup */
60#define CRYPTO_ERROR_NODEVICE -2 /* no device with vid:pid */
61#define CRYPTO_ERROR_BADENDP -3 /* device doesn't have the required endpoints */
62#define CRYPTO_ERROR_CLAIMFAIL -4 /* device interface claim error */
63#define CRYPTO_ERROR_DEVREJECT -5 /* device rejected cypto operation */
64#define CRYPTO_ERROR_DEVSILENT -6 /* device did not notify completion */
65#define CRYPTO_ERROR_DEVERR -7 /* device did something wrong (like return too small buffer) */
66#define CRYPTO_NUM_ERRORS 8
67/* return 0 on success, <0 on error */
68int crypto_apply(
69 byte *in_data, /* Input data */
70 byte *out_data, /* Output data (or NULL) */
71 int nr_blocks, /* Number of blocks (one block=16 bytes) */
72 byte iv[16], /* IV */
73 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
74 int encrypt);
75
76/* all-in-one function */
77struct crypto_key_t
78{
79 enum crypto_method_t method;
80 union
81 {
82 byte key[16];
83 uint32_t vid_pid;
84 byte param[0];
85 }u;
86};
87
88int crypto_cbc(
89 byte *in_data, /* Input data */
90 byte *out_data, /* Output data (or NULL) */
91 int nr_blocks, /* Number of blocks (one block=16 bytes) */
92 struct crypto_key_t *key, /* Key */
93 byte iv[16], /* IV */
94 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
95 int encrypt);
96
97/* crc.c */
98uint32_t crc(byte *data, int size);
99uint32_t crc_continue(uint32_t previous_crc, byte *data, int size);
100
101/* sha1.c */
102struct sha_1_params_t
103{
104 uint32_t hash[5];
105 uint64_t buffer_nr_bits;
106 uint32_t w[80];
107};
108
109void sha_1_init(struct sha_1_params_t *params);
110void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data);
111void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size);
112void sha_1_finish(struct sha_1_params_t *params);
113void sha_1_output(struct sha_1_params_t *params, byte *out);
114
115#endif /* __CRYPTO_H__ */
diff --git a/utils/imxtools/sbtools/dbparser.c b/utils/imxtools/sbtools/dbparser.c
new file mode 100644
index 0000000000..89a63b3767
--- /dev/null
+++ b/utils/imxtools/sbtools/dbparser.c
@@ -0,0 +1,857 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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
22#define _POSIX_C_SOURCE 200809L /* for strdup */
23#include <stdio.h>
24#include <ctype.h>
25#include <stdint.h>
26#include <string.h>
27#include "dbparser.h"
28#include "misc.h"
29
30enum lexem_type_t
31{
32 LEX_IDENTIFIER,
33 LEX_LPAREN,
34 LEX_RPAREN,
35 LEX_NUMBER,
36 LEX_STRING, /* double-quoted string */
37 LEX_EQUAL,
38 LEX_SEMICOLON,
39 LEX_LBRACE,
40 LEX_RBRACE,
41 LEX_RANGLE,
42 LEX_OR,
43 LEX_LSHIFT,
44 LEX_COLON,
45 LEX_LE,
46 LEX_EOF
47};
48
49struct lexem_t
50{
51 enum lexem_type_t type;
52 /* if str is not NULL, it must be a malloc'd pointer */
53 char *str;
54 uint32_t num;
55 int line;
56 const char *file;
57};
58
59struct context_t
60{
61 const char *file;
62 char *begin;
63 char *end;
64 char *ptr;
65 int line;
66};
67
68#define parse_error(ctx, ...) \
69 do { fprintf(stderr, "%s:%d: ", ctx->file, ctx->line); \
70 fprintf(stderr, __VA_ARGS__); exit(2); } while(0)
71
72static void advance(struct context_t *ctx, int nr_chars)
73{
74 while(nr_chars--)
75 {
76 if(*(ctx->ptr++) == '\n')
77 ctx->line++;
78 }
79}
80
81static inline bool eof(struct context_t *ctx)
82{
83 return ctx->ptr == ctx->end;
84}
85
86static inline bool next_valid(struct context_t *ctx, int nr)
87{
88 return ctx->ptr + nr < ctx->end;
89}
90
91static inline char cur_char(struct context_t *ctx)
92{
93 return *ctx->ptr;
94}
95
96static inline char next_char(struct context_t *ctx, int nr)
97{
98 return ctx->ptr[nr];
99}
100
101static inline void locate_lexem(struct lexem_t *lex, struct context_t *ctx)
102{
103 lex->file = ctx->file;
104 lex->line = ctx->line;
105}
106
107static void __parse_string(struct context_t *ctx, void *user, void (*emit_fn)(void *user, char c))
108{
109 while(!eof(ctx))
110 {
111 if(cur_char(ctx) == '"')
112 break;
113 else if(cur_char(ctx) == '\\')
114 {
115 advance(ctx, 1);
116 if(eof(ctx))
117 parse_error(ctx, "Unfinished string\n");
118 if(cur_char(ctx) == '\\') emit_fn(user, '\\');
119 else if(cur_char(ctx) == '\'') emit_fn(user, '\'');
120 else if(cur_char(ctx) == '\"') emit_fn(user, '\"');
121 else parse_error(ctx, "Unknown escape sequence \\%c\n", cur_char(ctx));
122 advance(ctx, 1);
123 }
124 else
125 {
126 emit_fn(user, cur_char(ctx));
127 advance(ctx, 1);
128 }
129 }
130 if(eof(ctx) || cur_char(ctx) != '"')
131 parse_error(ctx, "Unfinished string\n");
132 advance(ctx, 1);
133}
134
135static void __parse_string_emit(void *user, char c)
136{
137 char **pstr = (char **)user;
138 *(*pstr)++ = c;
139}
140
141static void __parse_string_count(void *user, char c)
142{
143 (void) c;
144 (*(int *)user)++;
145}
146
147static void parse_string(struct context_t *ctx, struct lexem_t *lexem)
148{
149 locate_lexem(lexem, ctx);
150 /* skip " */
151 advance(ctx, 1);
152 /* compute length */
153 struct context_t cpy_ctx = *ctx;
154 int length = 0;
155 __parse_string(&cpy_ctx, (void *)&length, __parse_string_count);
156 /* parse again */
157 lexem->type = LEX_STRING;
158 lexem->str = xmalloc(length + 1);
159 lexem->str[length] = 0;
160 char *pstr = lexem->str;
161 __parse_string(ctx, (void *)&pstr, __parse_string_emit);
162}
163
164static void parse_ascii_number(struct context_t *ctx, struct lexem_t *lexem)
165{
166 locate_lexem(lexem, ctx);
167 /* skip ' */
168 advance(ctx, 1);
169 /* we expect n<=4 character and then ' */
170 int len = 0;
171 uint32_t value = 0;
172 while(!eof(ctx))
173 {
174 if(cur_char(ctx) != '\'')
175 {
176 value = value << 8 | cur_char(ctx);
177 len++;
178 advance(ctx, 1);
179 }
180 else
181 break;
182 }
183 if(eof(ctx) || cur_char(ctx) != '\'')
184 parse_error(ctx, "Unterminated ascii number literal\n");
185 if(len == 0 || len > 4)
186 parse_error(ctx, "Invalid ascii number literal length: only 1 to 4 characters allowed\n");
187 /* skip ' */
188 advance(ctx, 1);
189 lexem->type = LEX_NUMBER;
190 lexem->num = value;
191}
192
193static void parse_number(struct context_t *ctx, struct lexem_t *lexem)
194{
195 locate_lexem(lexem, ctx);
196 /* check base */
197 int base = 10;
198 if(cur_char(ctx) == '0' && next_valid(ctx, 1) && next_char(ctx, 1) == 'x')
199 {
200 advance(ctx, 2);
201 base = 16;
202 }
203
204 lexem->type = LEX_NUMBER;
205 lexem->num = 0;
206 while(!eof(ctx) && isxdigit(cur_char(ctx)))
207 {
208 if(base == 10 && !isdigit(cur_char(ctx)))
209 break;
210 byte v;
211 if(convxdigit(cur_char(ctx), &v))
212 break;
213 lexem->num = base * lexem->num + v;
214 advance(ctx, 1);
215 }
216}
217
218static void parse_identifier(struct context_t *ctx, struct lexem_t *lexem)
219{
220 locate_lexem(lexem, ctx);
221 /* remember position */
222 char *old = ctx->ptr;
223 while(!eof(ctx) && (isalnum(cur_char(ctx)) || cur_char(ctx) == '_'))
224 advance(ctx, 1);
225 lexem->type = LEX_IDENTIFIER;
226 int len = ctx->ptr - old;
227 lexem->str = xmalloc(len + 1);
228 lexem->str[len] = 0;
229 memcpy(lexem->str, old, len);
230}
231
232static void next_lexem(struct context_t *ctx, struct lexem_t *lexem)
233{
234 #define ret_simple(t, adv) \
235 do {locate_lexem(lexem, ctx); \
236 lexem->type = t; \
237 advance(ctx, adv); \
238 return;} while(0)
239 while(!eof(ctx))
240 {
241 char c = cur_char(ctx);
242 /* skip whitespace */
243 if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
244 {
245 advance(ctx, 1);
246 continue;
247 }
248 /* skip C++ style comments */
249 if(c == '/' && next_valid(ctx, 1) && next_char(ctx, 1) == '/')
250 {
251 while(!eof(ctx) && cur_char(ctx) != '\n')
252 advance(ctx, 1);
253 continue;
254 }
255 /* skip C-style comments */
256 if(c == '/' && next_valid(ctx, 1) && next_char(ctx, 1) == '*')
257 {
258 advance(ctx, 2);
259 while(true)
260 {
261 if(!next_valid(ctx, 1))
262 parse_error(ctx, "Unterminated comment");
263 if(cur_char(ctx) == '*' && next_char(ctx, 1) == '/')
264 {
265 advance(ctx, 2);
266 break;
267 }
268 advance(ctx, 1);
269 }
270 continue;
271 }
272 break;
273 }
274 if(eof(ctx)) ret_simple(LEX_EOF, 0);
275 char c = cur_char(ctx);
276 bool nv = next_valid(ctx, 1);
277 char nc = nv ? next_char(ctx, 1) : 0;
278 if(c == '(') ret_simple(LEX_LPAREN, 1);
279 if(c == ')') ret_simple(LEX_RPAREN, 1);
280 if(c == '{') ret_simple(LEX_LBRACE, 1);
281 if(c == '}') ret_simple(LEX_RBRACE, 1);
282 if(c == '>') ret_simple(LEX_RANGLE, 1);
283 if(c == '=') ret_simple(LEX_EQUAL, 1);
284 if(c == ';') ret_simple(LEX_SEMICOLON, 1);
285 if(c == ',') ret_simple(LEX_COLON, 1);
286 if(c == '|') ret_simple(LEX_OR, 1);
287 if(c == '<' && nv && nc == '<') ret_simple(LEX_LSHIFT, 2);
288 if(c == '<' && nv && nc == '=') ret_simple(LEX_LE, 2);
289 if(c == '"') return parse_string(ctx, lexem);
290 if(c == '\'') return parse_ascii_number(ctx, lexem);
291 if(isdigit(c)) return parse_number(ctx, lexem);
292 if(isalpha(c) || c == '_') return parse_identifier(ctx, lexem);
293 parse_error(ctx, "Unexpected character '%c'\n", c);
294 #undef ret_simple
295}
296
297#if 0
298static void log_lexem(struct lexem_t *lexem)
299{
300 switch(lexem->type)
301 {
302 case LEX_EOF: printf("<eof>"); break;
303 case LEX_EQUAL: printf("="); break;
304 case LEX_IDENTIFIER: printf("id(%s)", lexem->str); break;
305 case LEX_LPAREN: printf("("); break;
306 case LEX_RPAREN: printf(")"); break;
307 case LEX_LBRACE: printf("{"); break;
308 case LEX_RBRACE: printf("}"); break;
309 case LEX_SEMICOLON: printf(";"); break;
310 case LEX_NUMBER: printf("num(%d)", lexem->num); break;
311 case LEX_STRING: printf("str(%s)", lexem->str); break;
312 case LEX_OR: printf("|"); break;
313 case LEX_LSHIFT: printf("<<"); break;
314 default: printf("<unk>");
315 }
316}
317#endif
318
319struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id)
320{
321 struct cmd_source_t *src = cmd_file->source_list;
322 while(src)
323 {
324 if(strcmp(src->identifier, id) == 0)
325 return src;
326 src = src->next;
327 }
328 return NULL;
329}
330
331struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *name)
332{
333 while(opt)
334 {
335 if(strcmp(opt->name, name) == 0)
336 return opt;
337 opt = opt->next;
338 }
339 return NULL;
340}
341
342#define INVALID_SB_SUBVERSION 0xffff
343
344static uint16_t parse_sb_subversion(char *str)
345{
346 int len = strlen(str);
347 uint16_t n = 0;
348 if(len == 0 || len > 4)
349 return INVALID_SB_SUBVERSION;
350 for(int i = 0; i < len; i++)
351 {
352 if(!isdigit(str[i]))
353 return INVALID_SB_SUBVERSION;
354 n = n << 4 | (str[i] - '0');
355 }
356 return n;
357}
358
359bool db_parse_sb_version(struct sb_version_t *ver, char *str)
360{
361 int len = strlen(str);
362 int cnt = 0;
363 int pos[2];
364
365 for(int i = 0; i < len; i++)
366 {
367 if(str[i] != '.')
368 continue;
369 if(cnt == 2)
370 return false;
371 pos[cnt++] = i + 1;
372 str[i] = 0;
373 }
374 if(cnt != 2)
375 return false;
376 ver->major = parse_sb_subversion(str);
377 ver->minor = parse_sb_subversion(str + pos[0]);
378 ver->revision = parse_sb_subversion(str + pos[1]);
379 return ver->major != INVALID_SB_SUBVERSION &&
380 ver->minor != INVALID_SB_SUBVERSION &&
381 ver->revision != INVALID_SB_SUBVERSION;
382}
383
384#undef parse_error
385#define parse_error(lexem, ...) \
386 do { fprintf(stderr, "%s:%d: ", lexem.file, lexem.line); \
387 fprintf(stderr, __VA_ARGS__); exit(2); } while(0)
388
389struct lex_ctx_t
390{
391 struct context_t ctx;
392 struct lexem_t lexem;
393};
394
395/* When lexems hold strings (like identifier), it might be useful to steal
396 * the pointer and don't clean the lexem but in other case, one don't want
397 * to keep the pointer to the string and just want to release the memory.
398 * Thus clean_lexem should be true except when one keeps a pointer */
399static inline void next(struct lex_ctx_t *ctx, bool clean_lexem)
400{
401 if(clean_lexem)
402 free(ctx->lexem.str);
403 memset(&ctx->lexem, 0, sizeof(struct lexem_t));
404 next_lexem(&ctx->ctx, &ctx->lexem);
405}
406
407static uint32_t parse_term_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list)
408{
409 uint32_t ret = 0;
410 if(ctx->lexem.type == LEX_NUMBER)
411 ret = ctx->lexem.num;
412 else if(ctx->lexem.type == LEX_IDENTIFIER)
413 {
414 struct cmd_option_t *c = db_find_option_by_id(const_list, ctx->lexem.str);
415 if(c == NULL)
416 parse_error(ctx->lexem, "Undefined reference to constant '%s'\n", ctx->lexem.str);
417 if(c->is_string)
418 parse_error(ctx->lexem, "Internal error: constant '%s' is not an integer\n", ctx->lexem.str);
419 ret = c->val;
420 }
421 else
422 parse_error(ctx->lexem, "Number or constant identifier expected\n");
423 next(ctx, true);
424 return ret;
425}
426
427static uint32_t parse_shift_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list)
428{
429 uint32_t v = parse_term_expr(ctx, const_list);
430 while(ctx->lexem.type == LEX_LSHIFT)
431 {
432 next(ctx, true);
433 v <<= parse_term_expr(ctx, const_list);
434 }
435 return v;
436}
437
438static uint32_t parse_or_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list)
439{
440 uint32_t v = parse_shift_expr(ctx, const_list);
441 while(ctx->lexem.type == LEX_OR)
442 {
443 next(ctx, true);
444 v |= parse_shift_expr(ctx, const_list);
445 }
446 return v;
447}
448
449static uint32_t parse_intexpr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list)
450{
451 return parse_or_expr(ctx, const_list);
452}
453
454#define NR_INITIAL_CONSTANTS 4
455static char *init_const_name[NR_INITIAL_CONSTANTS] = {"true", "false", "yes", "no"};
456static uint32_t init_const_value[NR_INITIAL_CONSTANTS] = {1, 0, 1, 0};
457
458struct cmd_file_t *db_parse_file(const char *file)
459{
460 size_t size;
461 FILE *f = fopen(file, "r");
462 if(f == NULL)
463 {
464 if(g_debug)
465 perror("Cannot open db file");
466 return NULL;
467 }
468 fseek(f, 0, SEEK_END);
469 size = ftell(f);
470 fseek(f, 0, SEEK_SET);
471 char *buf = xmalloc(size);
472 if(fread(buf, size, 1, f) != 1)
473 {
474 if(g_debug)
475 perror("Cannot read db file");
476 return NULL;
477 }
478 fclose(f);
479
480 if(g_debug)
481 printf("Parsing db file '%s'\n", file);
482 struct cmd_file_t *cmd_file = xmalloc(sizeof(struct cmd_file_t));
483 memset(cmd_file, 0, sizeof(struct cmd_file_t));
484
485 /* add initial constants */
486 for(int i = 0; i < NR_INITIAL_CONSTANTS; i++)
487 {
488 struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
489 memset(opt, 0, sizeof(struct cmd_option_t));
490 opt->name = strdup(init_const_name[i]);
491 opt->is_string = false;
492 opt->val = init_const_value[i];
493 opt->next = cmd_file->constant_list;
494 cmd_file->constant_list = opt;
495 }
496
497 struct lex_ctx_t lctx;
498 lctx.ctx.file = file;
499 lctx.ctx.line = 1;
500 lctx.ctx.begin = buf;
501 lctx.ctx.ptr = buf;
502 lctx.ctx.end = buf + size;
503 #define next(clean_lexem) next(&lctx, clean_lexem)
504 #define lexem lctx.lexem
505 /* init lexer */
506 next(false); /* don't clean init lexem because it doesn't exist */
507 /* constants ? */
508 if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants"))
509 {
510 next(true);
511 if(lexem.type != LEX_LBRACE)
512 parse_error(lexem, "'{' expected after 'constants'\n");
513
514 while(true)
515 {
516 struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
517 memset(opt, 0, sizeof(struct cmd_option_t));
518 next(true);
519 if(lexem.type == LEX_RBRACE)
520 break;
521 if(lexem.type != LEX_IDENTIFIER)
522 parse_error(lexem, "Identifier expected in constants\n");
523 opt->name = lexem.str;
524 next(false); /* lexem string is kept as option name */
525 if(lexem.type != LEX_EQUAL)
526 parse_error(lexem, "'=' expected after identifier\n");
527 next(true);
528 opt->is_string = false;
529 opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
530 opt->next = cmd_file->constant_list;
531 cmd_file->constant_list = opt;
532 if(lexem.type != LEX_SEMICOLON)
533 parse_error(lexem, "';' expected after string\n");
534 }
535 next(true);
536 }
537 /* options ? */
538 if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options"))
539 {
540 next(true);
541 if(lexem.type != LEX_LBRACE)
542 parse_error(lexem, "'{' expected after 'options'\n");
543
544 while(true)
545 {
546 next(true);
547 if(lexem.type == LEX_RBRACE)
548 break;
549 struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
550 memset(opt, 0, sizeof(struct cmd_option_t));
551 if(lexem.type != LEX_IDENTIFIER)
552 parse_error(lexem, "Identifier expected in options\n");
553 opt->name = lexem.str;
554 next(false); /* lexem string is kept as option name */
555 if(lexem.type != LEX_EQUAL)
556 parse_error(lexem, "'=' expected after identifier\n");
557 next(true);
558 if(lexem.type == LEX_STRING)
559 {
560 opt->is_string = true;
561 opt->str = lexem.str;
562 next(false); /* lexem string is kept as option name */
563 }
564 else
565 {
566 opt->is_string = false;
567 opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
568 }
569 opt->next = cmd_file->opt_list;
570 cmd_file->opt_list = opt;
571 if(lexem.type != LEX_SEMICOLON)
572 parse_error(lexem, "';' expected after string\n");
573 }
574 next(true);
575 }
576 /* sources */
577 if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources"))
578 parse_error(lexem, "'sources' expected\n");
579 next(true);
580 if(lexem.type != LEX_LBRACE)
581 parse_error(lexem, "'{' expected after 'sources'\n");
582
583 while(true)
584 {
585 next(true);
586 if(lexem.type == LEX_RBRACE)
587 break;
588 struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t));
589 memset(src, 0, sizeof(struct cmd_source_t));
590 if(lexem.type != LEX_IDENTIFIER)
591 parse_error(lexem, "identifier expected in sources\n");
592 src->identifier = lexem.str;
593 next(false); /* lexem string is kept as source name */
594 if(lexem.type != LEX_EQUAL)
595 parse_error(lexem, "'=' expected after identifier\n");
596 next(true);
597 if(lexem.type == LEX_STRING)
598 {
599 src->is_extern = false;
600 src->filename = lexem.str;
601 next(false); /* lexem string is kept as file name */
602 }
603 else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern"))
604 {
605 src->is_extern = true;
606 src->filename = strdup("<extern>"); /* duplicate because it will be free'd */
607 next(true);
608 if(lexem.type != LEX_LPAREN)
609 parse_error(lexem, "'(' expected after 'extern'\n");
610 next(true);
611 src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list);
612 if(lexem.type != LEX_RPAREN)
613 parse_error(lexem, "')' expected\n");
614 next(true);
615 }
616 else
617 parse_error(lexem, "String or 'extern' expected after '='\n");
618 if(lexem.type != LEX_SEMICOLON)
619 parse_error(lexem, "';' expected\n");
620 if(db_find_source_by_id(cmd_file, src->identifier) != NULL)
621 parse_error(lexem, "Duplicate source identifier\n");
622 /* type filled later */
623 src->type = CMD_SRC_UNK;
624 src->next = cmd_file->source_list;
625 cmd_file->source_list = src;
626 }
627
628 /* sections */
629 struct cmd_section_t *end_sec = NULL;
630 while(true)
631 {
632 next(true);
633 if(lexem.type == LEX_EOF)
634 break;
635 struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t));
636 struct cmd_inst_t *end_list = NULL;
637 memset(sec, 0, sizeof(struct cmd_section_t));
638 if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0)
639 parse_error(lexem, "'section' expected\n");
640 next(true);
641 if(lexem.type != LEX_LPAREN)
642 parse_error(lexem, "'(' expected after 'section'\n");
643 next(true);
644 /* can be any number */
645 sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list);
646 /* options ? */
647 if(lexem.type == LEX_SEMICOLON)
648 {
649 do
650 {
651 next(true);
652 struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
653 memset(opt, 0, sizeof(struct cmd_option_t));
654 if(lexem.type != LEX_IDENTIFIER)
655 parse_error(lexem, "Identifier expected for section option\n");
656 opt->name = lexem.str;
657 next(false); /* lexem string is kept as option name */
658 if(lexem.type != LEX_EQUAL)
659 parse_error(lexem, "'=' expected after option identifier\n");
660 next(true);
661 if(lexem.type == LEX_STRING)
662 {
663 opt->is_string = true;
664 opt->str = lexem.str;
665 next(false); /* lexem string is kept as option string */
666 }
667 else
668 {
669 opt->is_string = false;
670 opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
671 }
672 opt->next = sec->opt_list;
673 sec->opt_list = opt;
674 }while(lexem.type == LEX_COLON);
675 }
676 if(lexem.type != LEX_RPAREN)
677 parse_error(lexem, "')' expected after section identifier\n");
678 next(true);
679 if(lexem.type == LEX_LBRACE)
680 {
681 sec->is_data = false;
682 /* commands */
683 while(true)
684 {
685 next(true);
686 if(lexem.type == LEX_RBRACE)
687 break;
688 struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t));
689 memset(inst, 0, sizeof(struct cmd_inst_t));
690 if(lexem.type != LEX_IDENTIFIER)
691 parse_error(lexem, "Instruction expected in section\n");
692 if(strcmp(lexem.str, "load") == 0)
693 inst->type = CMD_LOAD;
694 else if(strcmp(lexem.str, "call") == 0)
695 inst->type = CMD_CALL;
696 else if(strcmp(lexem.str, "jump") == 0)
697 inst->type = CMD_JUMP;
698 else if(strcmp(lexem.str, "mode") == 0)
699 inst->type = CMD_MODE;
700 else
701 parse_error(lexem, "Instruction expected in section\n");
702 next(true);
703
704 if(inst->type == CMD_LOAD)
705 {
706 if(lexem.type != LEX_IDENTIFIER)
707 parse_error(lexem, "Identifier expected after instruction\n");
708 inst->identifier = lexem.str;
709 if(db_find_source_by_id(cmd_file, inst->identifier) == NULL)
710 parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier);
711 next(false); /* lexem string kept as identifier */
712 if(lexem.type == LEX_RANGLE)
713 {
714 // load at
715 inst->type = CMD_LOAD_AT;
716 next(true);
717 inst->addr = parse_intexpr(&lctx, cmd_file->constant_list);
718 }
719 if(lexem.type != LEX_SEMICOLON)
720 parse_error(lexem, "';' expected after command\n");
721 }
722 else if(inst->type == CMD_CALL || inst->type == CMD_JUMP)
723 {
724 if(lexem.type == LEX_IDENTIFIER)
725 {
726 inst->identifier = lexem.str;
727 if(db_find_source_by_id(cmd_file, inst->identifier) == NULL)
728 parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier);
729 next(false); /* lexem string kept as identifier */
730 }
731 else
732 {
733 inst->type = (inst->type == CMD_CALL) ? CMD_CALL_AT : CMD_JUMP_AT;
734 inst->addr = parse_intexpr(&lctx, cmd_file->constant_list);
735 }
736
737 if(lexem.type == LEX_LPAREN)
738 {
739 next(true);
740 inst->argument = parse_intexpr(&lctx, cmd_file->constant_list);
741 if(lexem.type != LEX_RPAREN)
742 parse_error(lexem, "Expected closing brace\n");
743 next(true);
744 }
745 if(lexem.type != LEX_SEMICOLON)
746 parse_error(lexem, "';' expected after command\n");
747 }
748 else if(inst->type == CMD_MODE)
749 {
750 inst->argument = parse_intexpr(&lctx, cmd_file->constant_list);
751 if(lexem.type != LEX_SEMICOLON)
752 parse_error(lexem, "Expected ';' after command\n");
753 }
754 else
755 parse_error(lexem, "Internal error");
756 if(end_list == NULL)
757 {
758 sec->inst_list = inst;
759 end_list = inst;
760 }
761 else
762 {
763 end_list->next = inst;
764 end_list = inst;
765 }
766 }
767 }
768 else if(lexem.type == LEX_LE)
769 {
770 sec->is_data = true;
771 next(true);
772 if(lexem.type != LEX_IDENTIFIER)
773 parse_error(lexem, "Identifier expected after '<='\n");
774 sec->source_id = lexem.str;
775 next(false); /* lexem string is kept as source id */
776 if(lexem.type != LEX_SEMICOLON)
777 parse_error(lexem, "';' expected after identifier\n");
778 }
779 else
780 parse_error(lexem, "'{' or '<=' expected after section directive\n");
781
782 if(end_sec == NULL)
783 {
784 cmd_file->section_list = sec;
785 end_sec = sec;
786 }
787 else
788 {
789 end_sec->next = sec;
790 end_sec = sec;
791 }
792 }
793 #undef lexem
794 #undef next
795
796 free(buf);
797 return cmd_file;
798}
799
800void db_generate_default_sb_version(struct sb_version_t *ver)
801{
802 ver->major = ver->minor = ver->revision = 0x999;
803}
804
805void db_free_option_list(struct cmd_option_t *opt_list)
806{
807 while(opt_list)
808 {
809 struct cmd_option_t *next = opt_list->next;
810 fflush(stdout);
811 free(opt_list->name);
812 free(opt_list->str);
813 free(opt_list);
814 opt_list = next;
815 }
816}
817
818void db_free(struct cmd_file_t *file)
819{
820 db_free_option_list(file->opt_list);
821 db_free_option_list(file->constant_list);
822 struct cmd_source_t *src = file->source_list;
823 while(src)
824 {
825 struct cmd_source_t *next = src->next;
826 free(src->identifier);
827 fflush(stdout);
828 free(src->filename);
829 if(src->loaded)
830 {
831 if(src->type == CMD_SRC_BIN)
832 free(src->bin.data);
833 if(src->type == CMD_SRC_ELF)
834 elf_release(&src->elf);
835 }
836 free(src);
837 src = next;
838 }
839 struct cmd_section_t *sec = file->section_list;
840 while(sec)
841 {
842 struct cmd_section_t *next = sec->next;
843 db_free_option_list(sec->opt_list);
844 free(sec->source_id);
845 struct cmd_inst_t *inst = sec->inst_list;
846 while(inst)
847 {
848 struct cmd_inst_t *next = inst->next;
849 free(inst->identifier);
850 free(inst);
851 inst = next;
852 }
853 free(sec);
854 sec = next;
855 }
856 free(file);
857}
diff --git a/utils/imxtools/sbtools/dbparser.h b/utils/imxtools/sbtools/dbparser.h
new file mode 100644
index 0000000000..4a36861583
--- /dev/null
+++ b/utils/imxtools/sbtools/dbparser.h
@@ -0,0 +1,118 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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#ifndef __DBPARSER__
22#define __DBPARSER__
23
24/**
25 * Command file parsing
26 */
27#include "sb.h"
28#include "elf.h"
29
30enum cmd_source_type_t
31{
32 CMD_SRC_UNK,
33 CMD_SRC_ELF,
34 CMD_SRC_BIN
35};
36
37struct bin_param_t
38{
39 uint32_t size;
40 void *data;
41};
42
43struct cmd_source_t
44{
45 char *identifier;
46 bool is_extern;
47 // <union>
48 int extern_nr;
49 char *filename;
50 // </union>
51 struct cmd_source_t *next;
52 /* for later use */
53 enum cmd_source_type_t type;
54 bool loaded;
55 struct elf_params_t elf;
56 struct bin_param_t bin;
57};
58
59enum cmd_inst_type_t
60{
61 CMD_LOAD, /* load image */
62 CMD_JUMP, /* jump at image */
63 CMD_CALL, /* call image */
64 CMD_LOAD_AT, /* load binary at */
65 CMD_CALL_AT, /* call at address */
66 CMD_JUMP_AT, /* jump at address */
67 CMD_MODE, /* change boot mode */
68};
69
70struct cmd_inst_t
71{
72 enum cmd_inst_type_t type;
73 char *identifier;
74 uint32_t argument; // for jump, call, mode
75 uint32_t addr; // for 'at'
76 struct cmd_inst_t *next;
77};
78
79struct cmd_option_t
80{
81 char *name;
82 bool is_string;
83 /* <union> */
84 uint32_t val;
85 char *str;
86 /* </union> */
87 struct cmd_option_t *next;
88};
89
90struct cmd_section_t
91{
92 uint32_t identifier;
93 bool is_data;
94 // <union>
95 struct cmd_inst_t *inst_list;
96 char *source_id;
97 // </union>
98 struct cmd_section_t *next;
99 struct cmd_option_t *opt_list;
100};
101
102struct cmd_file_t
103{
104 struct cmd_option_t *opt_list;
105 struct cmd_option_t *constant_list; /* constant are always integers */
106 struct cmd_source_t *source_list;
107 struct cmd_section_t *section_list;
108};
109
110struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id);
111struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *name);
112bool db_parse_sb_version(struct sb_version_t *ver, char *str);
113void db_generate_default_sb_version(struct sb_version_t *ver);
114struct cmd_file_t *db_parse_file(const char *file);
115void db_free_option_list(struct cmd_option_t *opt_list);
116void db_free(struct cmd_file_t *file);
117
118#endif /* __DBPARSER__ */
diff --git a/utils/imxtools/sbtools/elf.c b/utils/imxtools/sbtools/elf.c
new file mode 100644
index 0000000000..481ab98dd6
--- /dev/null
+++ b/utils/imxtools/sbtools/elf.c
@@ -0,0 +1,575 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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 "elf.h"
22#include "misc.h"
23
24/**
25 * Definitions
26 * taken from elf.h linux header
27 * based on ELF specification
28 * based on ARM ELF specification
29 */
30typedef uint16_t Elf32_Half;
31
32typedef uint32_t Elf32_Word;
33typedef int32_t Elf32_Sword;
34typedef uint32_t Elf32_Addr;
35typedef uint32_t Elf32_Off;
36typedef uint16_t Elf32_Section;
37
38#define EI_NIDENT 16
39
40typedef struct
41{
42 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
43 Elf32_Half e_type; /* Object file type */
44 Elf32_Half e_machine; /* Architecture */
45 Elf32_Word e_version; /* Object file version */
46 Elf32_Addr e_entry; /* Entry point virtual address */
47 Elf32_Off e_phoff; /* Program header table file offset */
48 Elf32_Off e_shoff; /* Section header table file offset */
49 Elf32_Word e_flags; /* Processor-specific flags */
50 Elf32_Half e_ehsize; /* ELF header size in bytes */
51 Elf32_Half e_phentsize; /* Program header table entry size */
52 Elf32_Half e_phnum; /* Program header table entry count */
53 Elf32_Half e_shentsize; /* Section header table entry size */
54 Elf32_Half e_shnum; /* Section header table entry count */
55 Elf32_Half e_shstrndx; /* Section header string table index */
56}Elf32_Ehdr;
57
58#define EI_MAG0 0 /* File identification byte 0 index */
59#define ELFMAG0 0x7f /* Magic number byte 0 */
60
61#define EI_MAG1 1 /* File identification byte 1 index */
62#define ELFMAG1 'E' /* Magic number byte 1 */
63
64#define EI_MAG2 2 /* File identification byte 2 index */
65#define ELFMAG2 'L' /* Magic number byte 2 */
66
67#define EI_MAG3 3 /* File identification byte 3 index */
68#define ELFMAG3 'F' /* Magic number byte 3 */
69
70#define EI_CLASS 4 /* File class byte index */
71#define ELFCLASS32 1 /* 32-bit objects */
72
73#define EI_DATA 5 /* Data encoding byte index */
74#define ELFDATA2LSB 1 /* 2's complement, little endian */
75
76#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */
77
78#define EI_OSABI 7 /* OS ABI identification */
79#define ELFOSABI_NONE 0 /* UNIX System V ABI */
80#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
81#define ELFOSABI_ARM 97 /* ARM */
82
83#define EI_ABIVERSION 8 /* ABI version */
84
85#define EI_PAD 9 /* Byte index of padding bytes */
86
87#define ET_EXEC 2 /* Executable file */
88
89#define EM_ARM 40 /* ARM */
90
91#define EV_CURRENT 1 /* Current version */
92
93#define EF_ARM_HASENTRY 0x00000002
94
95#define SHN_UNDEF 0 /* Undefined section */
96
97typedef struct
98{
99 Elf32_Word sh_name; /* Section name (string tbl index) */
100 Elf32_Word sh_type; /* Section type */
101 Elf32_Word sh_flags; /* Section flags */
102 Elf32_Addr sh_addr; /* Section virtual addr at execution */
103 Elf32_Off sh_offset; /* Section file offset */
104 Elf32_Word sh_size; /* Section size in bytes */
105 Elf32_Word sh_link; /* Link to another section */
106 Elf32_Word sh_info; /* Additional section information */
107 Elf32_Word sh_addralign; /* Section alignment */
108 Elf32_Word sh_entsize; /* Entry size if section holds table */
109}Elf32_Shdr;
110
111#define SHT_NULL 0 /* Section header table entry unused */
112#define SHT_PROGBITS 1 /* Program data */
113#define SHT_SYMTAB 2 /* Symbol table */
114#define SHT_STRTAB 3 /* String table */
115#define SHT_RELA 4 /* Relocation entries with addends */
116#define SHT_HASH 5 /* Symbol hash table */
117#define SHT_DYNAMIC 6 /* Dynamic linking information */
118#define SHT_NOTE 7 /* Notes */
119#define SHT_NOBITS 8 /* Program space with no data (bss) */
120#define SHT_REL 9 /* Relocation entries, no addends */
121#define SHT_SHLIB 10 /* Reserved */
122#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
123#define SHT_INIT_ARRAY 14 /* Array of constructors */
124#define SHT_FINI_ARRAY 15 /* Array of destructors */
125#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
126#define SHT_GROUP 17 /* Section group */
127#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
128#define SHT_NUM 19 /* Number of defined types. */
129
130#define SHF_WRITE (1 << 0) /* Writable */
131#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
132#define SHF_EXECINSTR (1 << 2) /* Executable */
133#define SHF_MERGE (1 << 4) /* Might be merged */
134#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
135
136typedef struct
137{
138 Elf32_Word p_type; /* Segment type */
139 Elf32_Off p_offset; /* Segment file offset */
140 Elf32_Addr p_vaddr; /* Segment virtual address */
141 Elf32_Addr p_paddr; /* Segment physical address */
142 Elf32_Word p_filesz; /* Segment size in file */
143 Elf32_Word p_memsz; /* Segment size in memory */
144 Elf32_Word p_flags; /* Segment flags */
145 Elf32_Word p_align; /* Segment alignment */
146}Elf32_Phdr;
147
148#define PT_LOAD 1 /* Loadable program segment */
149
150#define PF_X (1 << 0) /* Segment is executable */
151#define PF_W (1 << 1) /* Segment is writable */
152#define PF_R (1 << 2) /* Segment is readable */
153
154void elf_init(struct elf_params_t *params)
155{
156 memset(params, 0, sizeof(struct elf_params_t));
157}
158
159extern void *xmalloc(size_t s);
160
161static struct elf_section_t *elf_add_section(struct elf_params_t *params)
162{
163 struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t));
164 if(params->first_section == NULL)
165 params->first_section = params->last_section = sec;
166 else
167 {
168 params->last_section->next = sec;
169 params->last_section = sec;
170 }
171 sec->next = NULL;
172
173 return sec;
174}
175
176static struct elf_segment_t *elf_add_segment(struct elf_params_t *params)
177{
178 struct elf_segment_t *seg = xmalloc(sizeof(struct elf_section_t));
179 if(params->first_segment == NULL)
180 params->first_segment = params->last_segment = seg;
181 else
182 {
183 params->last_segment->next = seg;
184 params->last_segment = seg;
185 }
186 seg->next = NULL;
187
188 return seg;
189}
190
191void elf_add_load_section(struct elf_params_t *params,
192 uint32_t load_addr, uint32_t size, const void *section)
193{
194 struct elf_section_t *sec = elf_add_section(params);
195
196 sec->type = EST_LOAD;
197 sec->addr = load_addr;
198 sec->size = size;
199 sec->section = xmalloc(size);
200 memcpy(sec->section, section, size);
201}
202
203void elf_add_fill_section(struct elf_params_t *params,
204 uint32_t fill_addr, uint32_t size, uint32_t pattern)
205{
206 if(pattern != 0x00)
207 {
208 printf("oops, non-zero filling, ignore fill section\n");
209 return;
210 }
211
212 struct elf_section_t *sec = elf_add_section(params);
213
214 sec->type = EST_FILL;
215 sec->addr = fill_addr;
216 sec->size = size;
217 sec->pattern = pattern;
218}
219
220void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
221 elf_printf_fn_t printf, void *user)
222{
223 (void) printf;
224
225 Elf32_Ehdr ehdr;
226 uint32_t phnum = 0;
227 struct elf_section_t *sec = params->first_section;
228 uint32_t offset = 0;
229 Elf32_Phdr phdr;
230 Elf32_Shdr shdr;
231 memset(&ehdr, 0, EI_NIDENT);
232
233 while(sec)
234 {
235 if(sec->type == EST_LOAD)
236 {
237 sec->offset = offset;
238 offset += sec->size;
239 }
240 else
241 {
242 sec->offset = 0;
243 }
244
245 phnum++;
246 sec = sec->next;
247 }
248
249 uint32_t strtbl_offset = offset;
250
251 ehdr.e_ident[EI_MAG0] = ELFMAG0;
252 ehdr.e_ident[EI_MAG1] = ELFMAG1;
253 ehdr.e_ident[EI_MAG2] = ELFMAG2;
254 ehdr.e_ident[EI_MAG3] = ELFMAG3;
255 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
256 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
257 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
258 ehdr.e_ident[EI_OSABI] = ELFOSABI_NONE;
259 ehdr.e_ident[EI_ABIVERSION] = 0;
260 ehdr.e_type = ET_EXEC;
261 ehdr.e_machine = EM_ARM;
262 ehdr.e_version = EV_CURRENT;
263 ehdr.e_entry = params->start_addr;
264 ehdr.e_flags = 0;
265 if(params->has_start_addr)
266 ehdr.e_flags |= EF_ARM_HASENTRY;
267 ehdr.e_ehsize = sizeof ehdr;
268 ehdr.e_phentsize = sizeof phdr;
269 ehdr.e_phnum = phnum;
270 ehdr.e_shentsize = sizeof shdr;
271 ehdr.e_shnum = phnum + 2; /* one for section 0 and one for string table */
272 ehdr.e_shstrndx = ehdr.e_shnum - 1;
273 ehdr.e_phoff = ehdr.e_ehsize;
274 ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize;
275
276 write(user, 0, &ehdr, sizeof ehdr);
277
278 /* allocate enough size to hold any combinaison of .text/.bss in the string table:
279 * - one empty name ("\0")
280 * - at most N names of the form ".textXXXX\0" or ".bssXXXX\0"
281 * - one name ".shstrtab\0" */
282 char *strtbl_content = malloc(1 + strlen(".shstrtab") + 1 +
283 phnum * (strlen(".textXXXX") + 1));
284
285 strtbl_content[0] = '\0';
286 strcpy(&strtbl_content[1], ".shstrtab");
287 uint32_t strtbl_index = 1 + strlen(".shstrtab") + 1;
288
289 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
290 ehdr.e_shnum * ehdr.e_shentsize;
291
292 sec = params->first_section;
293 offset = ehdr.e_phoff;
294 while(sec)
295 {
296 sec->offset += data_offset;
297
298 phdr.p_type = PT_LOAD;
299 if(sec->type == EST_LOAD)
300 phdr.p_offset = sec->offset;
301 else
302 phdr.p_offset = 0;
303 phdr.p_paddr = sec->addr;
304 phdr.p_vaddr = phdr.p_paddr; /* assume identity map ? */
305 phdr.p_memsz = sec->size;
306 if(sec->type == EST_LOAD)
307 phdr.p_filesz = phdr.p_memsz;
308 else
309 phdr.p_filesz = 0;
310 phdr.p_flags = PF_X | PF_W | PF_R;
311 phdr.p_align = 0;
312
313 write(user, offset, &phdr, sizeof phdr);
314
315 offset += sizeof(Elf32_Phdr);
316 sec = sec->next;
317 }
318
319 sec = params->first_section;
320 offset = ehdr.e_shoff;
321
322 {
323 shdr.sh_name = 0;
324 shdr.sh_type = SHT_NULL;
325 shdr.sh_flags = 0;
326 shdr.sh_addr = 0;
327 shdr.sh_offset = 0;
328 shdr.sh_size = 0;
329 shdr.sh_link = SHN_UNDEF;
330 shdr.sh_info = 0;
331 shdr.sh_addralign = 0;
332 shdr.sh_entsize = 0;
333
334 write(user, offset, &shdr, sizeof shdr);
335
336 offset += sizeof(Elf32_Shdr);
337 }
338
339 uint32_t text_idx = 0;
340 uint32_t bss_idx = 0;
341 while(sec)
342 {
343 shdr.sh_name = strtbl_index;
344 if(sec->type == EST_LOAD)
345 {
346 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".text%d", text_idx++);
347 shdr.sh_type = SHT_PROGBITS;
348 }
349 else
350 {
351 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".bss%d", bss_idx++);
352 shdr.sh_type = SHT_NOBITS;
353 }
354 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
355 shdr.sh_addr = sec->addr;
356 shdr.sh_offset = sec->offset;
357 shdr.sh_size = sec->size;
358 shdr.sh_link = SHN_UNDEF;
359 shdr.sh_info = 0;
360 shdr.sh_addralign = 1;
361 shdr.sh_entsize = 0;
362
363 write(user, offset, &shdr, sizeof shdr);
364
365 offset += sizeof(Elf32_Shdr);
366 sec = sec->next;
367 }
368
369 {
370 shdr.sh_name = 1;
371 shdr.sh_type = SHT_STRTAB;
372 shdr.sh_flags = 0;
373 shdr.sh_addr = 0;
374 shdr.sh_offset = strtbl_offset + data_offset;
375 shdr.sh_size = strtbl_index;
376 shdr.sh_link = SHN_UNDEF;
377 shdr.sh_info = 0;
378 shdr.sh_addralign = 1;
379 shdr.sh_entsize = 0;
380
381 write(user, offset, &shdr, sizeof shdr);
382
383 offset += sizeof(Elf32_Shdr);
384 }
385
386 sec = params->first_section;
387 while(sec)
388 {
389 if(sec->type == EST_LOAD)
390 write(user, sec->offset, sec->section, sec->size);
391 sec = sec->next;
392 }
393
394 write(user, strtbl_offset + data_offset, strtbl_content, strtbl_index);
395 free(strtbl_content);
396}
397
398bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
399 elf_printf_fn_t printf, void *user)
400{
401 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;})
402
403 /* read header */
404 Elf32_Ehdr ehdr;
405 if(!read(user, 0, &ehdr, sizeof(ehdr)))
406 {
407 printf(user, true, "error reading elf header\n");
408 return false;
409 }
410 /* basic checks */
411 if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
412 ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3)
413 error_printf("invalid elf header\n");
414 if(ehdr.e_ident[EI_CLASS] != ELFCLASS32)
415 error_printf("invalid elf class: must be a 32-bit object\n");
416 if(ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
417 error_printf("invalid elf data encoding: must be 32-bit lsb\n");
418 if(ehdr.e_ident[EI_VERSION] != EV_CURRENT)
419 error_printf("invalid elf version\n");
420 if(ehdr.e_type != ET_EXEC)
421 error_printf("invalid elf file: must be an executable file\n");
422 if(ehdr.e_machine != EM_ARM)
423 error_printf("invalid elf file: must target an arm machine\n");
424 if(ehdr.e_ehsize != sizeof(ehdr))
425 error_printf("invalid elf file: size header mismatch\n");
426 if(ehdr.e_phnum > 0 && ehdr.e_phentsize != sizeof(Elf32_Phdr))
427 error_printf("invalid elf file: program header size mismatch\n");
428 if(ehdr.e_shnum > 0 && ehdr.e_shentsize != sizeof(Elf32_Shdr))
429 error_printf("invalid elf file: section header size mismatch\n");
430 elf_set_start_addr(params, ehdr.e_entry);
431
432 char *strtab = NULL;
433 if(ehdr.e_shstrndx != SHN_UNDEF)
434 {
435 Elf32_Shdr shstrtab;
436 if(read(user, ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize,
437 &shstrtab, sizeof(shstrtab)))
438 {
439 strtab = xmalloc(shstrtab.sh_size);
440 if(!read(user, shstrtab.sh_offset, strtab, shstrtab.sh_size))
441 {
442 free(strtab);
443 strtab = NULL;
444 }
445 }
446 }
447 /* run through sections */
448 printf(user, false, "ELF file:\n");
449 for(int i = 1; i < ehdr.e_shnum; i++)
450 {
451 uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize;
452 Elf32_Shdr shdr;
453 memset(&shdr, 0, sizeof(shdr));
454 if(!read(user, off, &shdr, sizeof(shdr)))
455 error_printf("error reading elf section header");
456
457 if(shdr.sh_type == SHT_PROGBITS && shdr.sh_flags & SHF_ALLOC)
458 {
459 void *data = xmalloc(shdr.sh_size);
460 if(!read(user, shdr.sh_offset, data, shdr.sh_size))
461 error_printf("error read self section data\n");
462 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data);
463 free(data);
464
465 if(strtab)
466 printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]);
467 }
468 else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC)
469 {
470 elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0);
471 if(strtab)
472 printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]);
473 }
474 else
475 {
476 if(strtab)
477 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type);
478 }
479
480 }
481 free(strtab);
482 /* run through segments */
483 for(int i = 1; i < ehdr.e_phnum; i++)
484 {
485 uint32_t off = ehdr.e_phoff + i * ehdr.e_phentsize;
486 Elf32_Phdr phdr;
487 memset(&phdr, 0, sizeof(phdr));
488 if(!read(user, off, &phdr, sizeof(phdr)))
489 error_printf("error reading elf segment header");
490 if(phdr.p_type != PT_LOAD)
491 continue;
492 struct elf_segment_t *seg = elf_add_segment(params);
493 seg->vaddr = phdr.p_vaddr;
494 seg->paddr = phdr.p_paddr;
495 seg->vsize = phdr.p_memsz;
496 seg->psize = phdr.p_filesz;
497 printf(user, false, "create segment [%#x,+%#x[ -> [%#x,+%#x[\n",
498 seg->vaddr, seg->vsize, seg->paddr, seg->psize);
499 }
500
501 return true;
502}
503
504uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr)
505{
506 struct elf_segment_t *seg = params->first_segment;
507 while(seg)
508 {
509 if(seg->vaddr <= addr && addr < seg->vaddr + seg->vsize)
510 return addr - seg->vaddr + seg->paddr;
511 seg = seg->next;
512 }
513 return addr;
514}
515
516void elf_translate_addresses(struct elf_params_t *params)
517{
518 struct elf_section_t *sec = params->first_section;
519 while(sec)
520 {
521 sec->addr = elf_translate_virtual_address(params, sec->addr);
522 sec = sec->next;
523 }
524 params->start_addr = elf_translate_virtual_address(params, params->start_addr);
525}
526
527bool elf_is_empty(struct elf_params_t *params)
528{
529 return params->first_section == NULL;
530}
531
532void elf_set_start_addr(struct elf_params_t *params, uint32_t addr)
533{
534 params->has_start_addr = true;
535 params->start_addr = addr;
536}
537
538bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr)
539{
540 if(params->has_start_addr && addr != NULL)
541 *addr = params->start_addr;
542 return params->has_start_addr;
543}
544
545int elf_get_nr_sections(struct elf_params_t *params)
546{
547 int nr = 0;
548 struct elf_section_t *sec = params->first_section;
549 while(sec)
550 {
551 nr++;
552 sec = sec->next;
553 }
554 return nr;
555}
556
557void elf_release(struct elf_params_t *params)
558{
559 struct elf_section_t *sec = params->first_section;
560 while(sec)
561 {
562 struct elf_section_t *next_sec = sec->next;
563 if(sec->type == EST_LOAD)
564 free(sec->section);
565 free(sec);
566 sec = next_sec;
567 }
568 struct elf_segment_t *seg = params->first_segment;
569 while(seg)
570 {
571 struct elf_segment_t *next_seg = seg->next;
572 free(seg);
573 seg = next_seg;
574 }
575}
diff --git a/utils/imxtools/sbtools/elf.h b/utils/imxtools/sbtools/elf.h
new file mode 100644
index 0000000000..2166833276
--- /dev/null
+++ b/utils/imxtools/sbtools/elf.h
@@ -0,0 +1,94 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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#ifndef __ELF_H__
22#define __ELF_H__
23
24#include <stdio.h>
25#include <stdint.h>
26#include <string.h>
27#include <stdbool.h>
28#include <stdlib.h>
29#include <unistd.h>
30
31/**
32 * API
33 */
34enum elf_section_type_t
35{
36 EST_LOAD,
37 EST_FILL
38};
39
40struct elf_section_t
41{
42 uint32_t addr; /* virtual address */
43 uint32_t size; /* virtual size */
44 enum elf_section_type_t type;
45 /* <union> */
46 void *section; /* data */
47 uint32_t pattern; /* fill pattern */
48 /* </union> */
49 struct elf_section_t *next;
50 /* Internal to elf_write_file */
51 uint32_t offset;
52};
53
54struct elf_segment_t
55{
56 uint32_t vaddr; /* virtual address */
57 uint32_t paddr; /* physical address */
58 uint32_t vsize; /* virtual size */
59 uint32_t psize; /* physical size */
60 struct elf_segment_t *next;
61};
62
63struct elf_params_t
64{
65 bool has_start_addr;
66 uint32_t start_addr;
67 struct elf_section_t *first_section;
68 struct elf_section_t *last_section;
69 struct elf_segment_t *first_segment;
70 struct elf_segment_t *last_segment;
71};
72
73typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count);
74/* write function manages it's own error state */
75typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count);
76typedef void (*elf_printf_fn_t)(void *user, bool error, const char *fmt, ...);
77
78void elf_init(struct elf_params_t *params);
79void elf_add_load_section(struct elf_params_t *params,
80 uint32_t load_addr, uint32_t size, const void *section);
81void elf_add_fill_section(struct elf_params_t *params,
82 uint32_t fill_addr, uint32_t size, uint32_t pattern);
83uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr);
84void elf_translate_addresses(struct elf_params_t *params);
85void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, elf_printf_fn_t printf, void *user);
86bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, elf_printf_fn_t printf,
87 void *user);
88bool elf_is_empty(struct elf_params_t *params);
89void elf_set_start_addr(struct elf_params_t *params, uint32_t addr);
90bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr);
91int elf_get_nr_sections(struct elf_params_t *params);
92void elf_release(struct elf_params_t *params);
93
94#endif /* __ELF_H__ */
diff --git a/utils/imxtools/sbtools/elftosb.c b/utils/imxtools/sbtools/elftosb.c
new file mode 100644
index 0000000000..43bcf34849
--- /dev/null
+++ b/utils/imxtools/sbtools/elftosb.c
@@ -0,0 +1,462 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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
22#define _ISOC99_SOURCE
23#define _POSIX_C_SOURCE 200809L /* for strdup */
24#include <stdio.h>
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29#include <time.h>
30#include <stdarg.h>
31#include <strings.h>
32#include <getopt.h>
33
34#include "crypto.h"
35#include "elf.h"
36#include "sb.h"
37#include "dbparser.h"
38#include "misc.h"
39#include "sb.h"
40
41char **g_extern;
42int g_extern_count;
43
44#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
45
46#define crypto_cbc(...) \
47 do { int ret = crypto_cbc(__VA_ARGS__); \
48 if(ret != CRYPTO_ERROR_SUCCESS) \
49 bug("crypto_cbc error: %d\n", ret); \
50 }while(0)
51
52/**
53 * command file to sb conversion
54 */
55
56static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
57{
58 if(fseek((FILE *)user, addr, SEEK_SET) == -1)
59 return false;
60 return fread(buf, 1, count, (FILE *)user) == count;
61}
62
63static void elf_printf(void *user, bool error, const char *fmt, ...)
64{
65 if(!g_debug && !error)
66 return;
67 (void) user;
68 va_list args;
69 va_start(args, fmt);
70 vprintf(fmt, args);
71 va_end(args);
72}
73
74static void resolve_extern(struct cmd_source_t *src)
75{
76 if(!src->is_extern)
77 return;
78 src->is_extern = false;
79 if(src->extern_nr < 0 || src->extern_nr >= g_extern_count)
80 bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr);
81 /* first free the old src->filename content */
82 free(src->filename);
83 src->filename = strdup(g_extern[src->extern_nr]);
84}
85
86static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
87{
88 struct cmd_source_t *src = db_find_source_by_id(cmd_file, id);
89 if(src == NULL)
90 bug("undefined reference to source '%s'\n", id);
91 /* avoid reloading */
92 if(src->type == CMD_SRC_ELF && src->loaded)
93 return;
94 if(src->type != CMD_SRC_UNK)
95 bug("source '%s' seen both as elf and binary file\n", id);
96 /* resolve potential extern file */
97 resolve_extern(src);
98 /* load it */
99 src->type = CMD_SRC_ELF;
100 FILE *fd = fopen(src->filename, "rb");
101 if(fd == NULL)
102 bug("cannot open '%s' (id '%s')\n", src->filename, id);
103 if(g_debug)
104 printf("Loading ELF file '%s'...\n", src->filename);
105 elf_init(&src->elf);
106 src->loaded = elf_read_file(&src->elf, elf_read, elf_printf, fd);
107 fclose(fd);
108 if(!src->loaded)
109 bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
110 elf_translate_addresses(&src->elf);
111}
112
113static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
114{
115 struct cmd_source_t *src = db_find_source_by_id(cmd_file, id);
116 if(src == NULL)
117 bug("undefined reference to source '%s'\n", id);
118 /* avoid reloading */
119 if(src->type == CMD_SRC_BIN && src->loaded)
120 return;
121 if(src->type != CMD_SRC_UNK)
122 bug("source '%s' seen both as elf and binary file\n", id);
123 /* resolve potential extern file */
124 resolve_extern(src);
125 /* load it */
126 src->type = CMD_SRC_BIN;
127 FILE *fd = fopen(src->filename, "rb");
128 if(fd == NULL)
129 bug("cannot open '%s' (id '%s')\n", src->filename, id);
130 if(g_debug)
131 printf("Loading BIN file '%s'...\n", src->filename);
132 fseek(fd, 0, SEEK_END);
133 src->bin.size = ftell(fd);
134 fseek(fd, 0, SEEK_SET);
135 src->bin.data = xmalloc(src->bin.size);
136 fread(src->bin.data, 1, src->bin.size, fd);
137 fclose(fd);
138 src->loaded = true;
139}
140
141static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
142{
143 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t));
144 memset(sb, 0, sizeof(struct sb_file_t));
145
146 db_generate_default_sb_version(&sb->product_ver);
147 db_generate_default_sb_version(&sb->component_ver);
148
149 if(g_debug)
150 printf("Applying command file...\n");
151 /* count sections */
152 struct cmd_section_t *csec = cmd_file->section_list;
153 while(csec)
154 {
155 sb->nr_sections++;
156 csec = csec->next;
157 }
158
159 sb->sections = xmalloc(sb->nr_sections * sizeof(struct sb_section_t));
160 memset(sb->sections, 0, sb->nr_sections * sizeof(struct sb_section_t));
161 /* flatten sections */
162 csec = cmd_file->section_list;
163 for(int i = 0; i < sb->nr_sections; i++, csec = csec->next)
164 {
165 struct sb_section_t *sec = &sb->sections[i];
166 sec->identifier = csec->identifier;
167
168 /* options */
169 do
170 {
171 /* cleartext */
172 struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext");
173 if(opt != NULL)
174 {
175 if(opt->is_string)
176 bug("Cleartext section attribute must be an integer\n");
177 if(opt->val != 0 && opt->val != 1)
178 bug("Cleartext section attribute must be 0 or 1\n");
179 sec->is_cleartext = opt->val;
180 }
181 /* alignment */
182 opt = db_find_option_by_id(csec->opt_list, "alignment");
183 if(opt != NULL)
184 {
185 if(opt->is_string)
186 bug("Cleartext section attribute must be an integer\n");
187 // n is a power of 2 iff n & (n - 1) = 0
188 // alignement cannot be lower than block size
189 if((opt->val & (opt->val - 1)) != 0)
190 bug("Cleartext section attribute must be a power of two\n");
191 if(opt->val < BLOCK_SIZE)
192 sec->alignment = BLOCK_SIZE;
193 else
194 sec->alignment = opt->val;
195 }
196 else
197 sec->alignment = BLOCK_SIZE;
198 }while(0);
199
200 if(csec->is_data)
201 {
202 sec->is_data = true;
203 sec->nr_insts = 1;
204 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
205 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t));
206
207 load_bin_by_id(cmd_file, csec->source_id);
208 struct bin_param_t *bin = &db_find_source_by_id(cmd_file, csec->source_id)->bin;
209
210 sec->insts[0].inst = SB_INST_DATA;
211 sec->insts[0].size = bin->size;
212 sec->insts[0].data = memdup(bin->data, bin->size);
213 }
214 else
215 {
216 sec->is_data = false;
217 /* count instructions and loads things */
218 struct cmd_inst_t *cinst = csec->inst_list;
219 while(cinst)
220 {
221 if(cinst->type == CMD_LOAD)
222 {
223 load_elf_by_id(cmd_file, cinst->identifier);
224 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
225 sec->nr_insts += elf_get_nr_sections(elf);
226 }
227 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
228 {
229 load_elf_by_id(cmd_file, cinst->identifier);
230 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
231 if(!elf_get_start_addr(elf, NULL))
232 bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier);
233 sec->nr_insts++;
234 }
235 else if(cinst->type == CMD_CALL_AT || cinst->type == CMD_JUMP_AT)
236 {
237 sec->nr_insts++;
238 }
239 else if(cinst->type == CMD_LOAD_AT)
240 {
241 load_bin_by_id(cmd_file, cinst->identifier);
242 sec->nr_insts++;
243 }
244 else if(cinst->type == CMD_MODE)
245 {
246 sec->nr_insts++;
247 }
248 else
249 bug("die\n");
250
251 cinst = cinst->next;
252 }
253
254 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
255 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t));
256 /* flatten */
257 int idx = 0;
258 cinst = csec->inst_list;
259 while(cinst)
260 {
261 if(cinst->type == CMD_LOAD)
262 {
263 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
264 struct elf_section_t *esec = elf->first_section;
265 while(esec)
266 {
267 if(esec->type == EST_LOAD)
268 {
269 sec->insts[idx].inst = SB_INST_LOAD;
270 sec->insts[idx].addr = esec->addr;
271 sec->insts[idx].size = esec->size;
272 sec->insts[idx++].data = memdup(esec->section, esec->size);
273 }
274 else if(esec->type == EST_FILL)
275 {
276 sec->insts[idx].inst = SB_INST_FILL;
277 sec->insts[idx].addr = esec->addr;
278 sec->insts[idx].size = esec->size;
279 sec->insts[idx++].pattern = esec->pattern;
280 }
281 esec = esec->next;
282 }
283 }
284 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
285 {
286 struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf;
287 sec->insts[idx].argument = cinst->argument;
288 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
289 sec->insts[idx++].addr = elf->start_addr;
290 }
291 else if(cinst->type == CMD_JUMP_AT || cinst->type == CMD_CALL_AT)
292 {
293 sec->insts[idx].argument = cinst->argument;
294 sec->insts[idx].inst = (cinst->type == CMD_JUMP_AT) ? SB_INST_JUMP : SB_INST_CALL;
295 sec->insts[idx++].addr = cinst->addr;
296 }
297 else if(cinst->type == CMD_LOAD_AT)
298 {
299 struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin;
300 sec->insts[idx].inst = SB_INST_LOAD;
301 sec->insts[idx].addr = cinst->addr;
302 sec->insts[idx].data = memdup(bin->data, bin->size);
303 sec->insts[idx++].size = bin->size;
304 }
305 else if(cinst->type == CMD_MODE)
306 {
307 sec->insts[idx].inst = SB_INST_MODE;
308 sec->insts[idx++].addr = cinst->argument;
309 }
310 else
311 bug("die\n");
312
313 cinst = cinst->next;
314 }
315 }
316 }
317
318 return sb;
319}
320
321static void usage(void)
322{
323 printf("Usage: elftosb [options | file]...\n");
324 printf("Options:\n");
325 printf(" -?/--help\tDisplay this message\n");
326 printf(" -o <file>\tSet output file\n");
327 printf(" -c <file>\tSet command file\n");
328 printf(" -d/--debug\tEnable debug output\n");
329 printf(" -k <file>\tAdd key file\n");
330 printf(" -z\t\tAdd zero key\n");
331 printf(" --add-key <key>\tAdd single key (hex or usbotp)\n");
332 printf(" --real-key <key>\tOverride real key\n");
333 printf(" --crypto-iv <iv>\tOverride crypto IV\n");
334 exit(1);
335}
336
337static struct crypto_key_t g_zero_key =
338{
339 .method = CRYPTO_KEY,
340 .u.key = {0}
341};
342
343int main(int argc, char **argv)
344{
345 char *cmd_filename = NULL;
346 char *output_filename = NULL;
347 struct crypto_key_t real_key;
348 struct crypto_key_t crypto_iv;
349 real_key.method = CRYPTO_NONE;
350 crypto_iv.method = CRYPTO_NONE;
351
352 while(1)
353 {
354 static struct option long_options[] =
355 {
356 {"help", no_argument, 0, '?'},
357 {"debug", no_argument, 0, 'd'},
358 {"add-key", required_argument, 0, 'a'},
359 {"real-key", required_argument, 0, 'r'},
360 {"crypto-iv", required_argument, 0, 'i'},
361 {0, 0, 0, 0}
362 };
363
364 int c = getopt_long(argc, argv, "?do:c:k:za:", long_options, NULL);
365 if(c == -1)
366 break;
367 switch(c)
368 {
369 case 'd':
370 g_debug = true;
371 break;
372 case '?':
373 usage();
374 break;
375 case 'o':
376 output_filename = optarg;
377 break;
378 case 'c':
379 cmd_filename = optarg;
380 break;
381 case 'k':
382 {
383 if(!add_keys_from_file(optarg))
384 bug("Cannot keys from %s\n", optarg);
385 break;
386 }
387 case 'z':
388 {
389 add_keys(&g_zero_key, 1);
390 break;
391 }
392 case 'a':
393 case 'r':
394 case 'i':
395 {
396 struct crypto_key_t key;
397 char *s = optarg;
398 if(!parse_key(&s, &key))
399 bug("Invalid key/iv specified as argument");
400 if(*s != 0)
401 bug("Trailing characters after key/iv specified as argument");
402 if(c == 'r')
403 memcpy(&real_key, &key, sizeof(key));
404 else if(c == 'i')
405 memcpy(&crypto_iv, &key, sizeof(key));
406 else
407 add_keys(&key, 1);
408 break;
409 }
410 default:
411 abort();
412 }
413 }
414
415 if(!cmd_filename)
416 bug("You must specify a command file\n");
417 if(!output_filename)
418 bug("You must specify an output file\n");
419
420 g_extern = &argv[optind];
421 g_extern_count = argc - optind;
422
423 if(g_debug)
424 {
425 printf("key: %d\n", g_nr_keys);
426 for(int i = 0; i < g_nr_keys; i++)
427 {
428 printf(" ");
429 print_key(&g_key_array[i], true);
430 }
431
432 for(int i = 0; i < g_extern_count; i++)
433 printf("extern(%d)=%s\n", i, g_extern[i]);
434 }
435
436 struct cmd_file_t *cmd_file = db_parse_file(cmd_filename);
437 struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
438 db_free(cmd_file);
439
440 if(real_key.method == CRYPTO_KEY)
441 {
442 sb_file->override_real_key = true;
443 memcpy(sb_file->real_key, real_key.u.key, 16);
444 }
445 if(crypto_iv.method == CRYPTO_KEY)
446 {
447 sb_file->override_crypto_iv = true;
448 memcpy(sb_file->crypto_iv, crypto_iv.u.key, 16);
449 }
450
451 /* fill with default parameters since there is no command file support for them */
452 sb_file->drive_tag = 0;
453 sb_file->first_boot_sec_id = sb_file->sections[0].identifier;
454 sb_file->flags = 0;
455 sb_file->minor_version = 1;
456
457 sb_write_file(sb_file, output_filename);
458 sb_free(sb_file);
459 clear_keys();
460
461 return 0;
462}
diff --git a/utils/imxtools/sbtools/fuze+_key_file.txt b/utils/imxtools/sbtools/fuze+_key_file.txt
new file mode 100644
index 0000000000..a965e715f7
--- /dev/null
+++ b/utils/imxtools/sbtools/fuze+_key_file.txt
@@ -0,0 +1 @@
00000000000000000000000000000000
diff --git a/utils/imxtools/sbtools/misc.c b/utils/imxtools/sbtools/misc.c
new file mode 100644
index 0000000000..fce71ae0cd
--- /dev/null
+++ b/utils/imxtools/sbtools/misc.c
@@ -0,0 +1,265 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 <stdlib.h>
22#include <stdio.h>
23#include <time.h>
24#include <ctype.h>
25#include "misc.h"
26
27bool g_debug = false;
28
29/**
30 * Misc
31 */
32
33void *memdup(const void *p, size_t len)
34{
35 void *cpy = xmalloc(len);
36 memcpy(cpy, p, len);
37 return cpy;
38}
39
40void generate_random_data(void *buf, size_t sz)
41{
42 size_t i = 0;
43 unsigned char* p = (unsigned char*)buf;
44 while(i++ < sz)
45 *p++ = rand();
46}
47
48void *xmalloc(size_t s)
49{
50 void * r = malloc(s);
51 if(!r) bugp("malloc");
52 return r;
53}
54
55int convxdigit(char digit, byte *val)
56{
57 if(digit >= '0' && digit <= '9')
58 {
59 *val = digit - '0';
60 return 0;
61 }
62 else if(digit >= 'A' && digit <= 'F')
63 {
64 *val = digit - 'A' + 10;
65 return 0;
66 }
67 else if(digit >= 'a' && digit <= 'f')
68 {
69 *val = digit - 'a' + 10;
70 return 0;
71 }
72 else
73 return 1;
74}
75
76/* helper function to augment an array, free old array */
77void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt)
78{
79 void *p = xmalloc(elem_sz * (cnt + aug_cnt));
80 memcpy(p, arr, elem_sz * cnt);
81 memcpy(p + elem_sz * cnt, aug, elem_sz * aug_cnt);
82 free(arr);
83 return p;
84}
85
86/**
87 * Key file parsing
88 */
89int g_nr_keys;
90key_array_t g_key_array;
91
92bool parse_key(char **pstr, struct crypto_key_t *key)
93{
94 char *str = *pstr;
95 /* ignore spaces */
96 while(isspace(*str))
97 str++;
98 /* CRYPTO_KEY: 32 hex characters
99 * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers */
100 if(isxdigit(str[0]))
101 {
102 if(strlen(str) < 32)
103 return false;
104 for(int j = 0; j < 16; j++)
105 {
106 byte a, b;
107 if(convxdigit(str[2 * j], &a) || convxdigit(str[2 * j + 1], &b))
108 return false;
109 key->u.key[j] = (a << 4) | b;
110 }
111 /* skip key */
112 *pstr = str + 32;
113 key->method = CRYPTO_KEY;
114 return true;
115 }
116 else
117 {
118 const char *prefix = "usbotp(";
119 if(strlen(str) < strlen(prefix))
120 return false;
121 if(strncmp(str, prefix, strlen(prefix)) != 0)
122 return false;
123 str += strlen(prefix);
124 /* vid */
125 long vid = strtol(str, &str, 16);
126 if(vid < 0 || vid > 0xffff)
127 return false;
128 if(*str++ != ':')
129 return false;
130 /* pid */
131 long pid = strtol(str, &str, 16);
132 if(pid < 0 || pid > 0xffff)
133 return false;
134 if(*str++ != ')')
135 return false;
136 *pstr = str;
137 key->method = CRYPTO_USBOTP;
138 key->u.vid_pid = vid << 16 | pid;
139 return true;
140 }
141}
142
143void add_keys(key_array_t ka, int kac)
144{
145 key_array_t new_ka = xmalloc((g_nr_keys + kac) * sizeof(struct crypto_key_t));
146 memcpy(new_ka, g_key_array, g_nr_keys * sizeof(struct crypto_key_t));
147 memcpy(new_ka + g_nr_keys, ka, kac * sizeof(struct crypto_key_t));
148 free(g_key_array);
149 g_key_array = new_ka;
150 g_nr_keys += kac;
151}
152
153void clear_keys()
154{
155 free(g_key_array);
156 g_nr_keys = 0;
157 g_key_array = NULL;
158}
159
160bool add_keys_from_file(const char *key_file)
161{
162 int size;
163 FILE *fd = fopen(key_file, "r");
164 if(fd == NULL)
165 {
166 if(g_debug)
167 perror("cannot open key file");
168 return false;
169 }
170 fseek(fd, 0, SEEK_END);
171 size = ftell(fd);
172 fseek(fd, 0, SEEK_SET);
173 char *buf = xmalloc(size + 1);
174 if(fread(buf, 1, size, fd) != (size_t)size)
175 {
176 if(g_debug)
177 perror("Cannot read key file");
178 fclose(fd);
179 return false;
180 }
181 buf[size] = 0;
182 fclose(fd);
183
184 if(g_debug)
185 printf("Parsing key file '%s'...\n", key_file);
186 char *p = buf;
187 while(1)
188 {
189 struct crypto_key_t k;
190 /* parse key */
191 if(!parse_key(&p, &k))
192 {
193 if(g_debug)
194 printf("invalid key file\n");
195 return false;
196 }
197 if(g_debug)
198 {
199 printf("Add key: ");
200 print_key(&k, true);
201 }
202 add_keys(&k, 1);
203 /* request at least one space character before next key, or end of file */
204 if(*p != 0 && !isspace(*p))
205 {
206 if(g_debug)
207 printf("invalid key file\n");
208 return false;
209 }
210 /* skip whitespace */
211 while(isspace(*p))
212 p++;
213 if(*p == 0)
214 break;
215 }
216 free(buf);
217 return true;
218}
219
220void print_hex(byte *data, int len, bool newline)
221{
222 for(int i = 0; i < len; i++)
223 printf("%02X ", data[i]);
224 if(newline)
225 printf("\n");
226}
227
228void print_key(struct crypto_key_t *key, bool newline)
229{
230 switch(key->method)
231 {
232 case CRYPTO_KEY:
233 print_hex(key->u.key, 16, false);
234 break;
235 case CRYPTO_USBOTP:
236 printf("USB-OTP(%04x:%04x)", key->u.vid_pid >> 16, key->u.vid_pid & 0xffff);
237 break;
238 case CRYPTO_NONE:
239 printf("none");
240 break;
241 }
242 if(newline)
243 printf("\n");
244}
245
246char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
247
248char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
249char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
250char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
251char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
252char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
253
254static bool g_color_enable = true;
255
256void enable_color(bool enable)
257{
258 g_color_enable = enable;
259}
260
261void color(color_t c)
262{
263 if(g_color_enable)
264 printf("%s", (char *)c);
265}
diff --git a/utils/imxtools/sbtools/misc.h b/utils/imxtools/sbtools/misc.h
new file mode 100644
index 0000000000..4df9bbe957
--- /dev/null
+++ b/utils/imxtools/sbtools/misc.h
@@ -0,0 +1,59 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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#ifndef __MISC_H__
22#define __MISC_H__
23
24#include <stdbool.h>
25#include "crypto.h"
26
27#define _STR(a) #a
28#define STR(a) _STR(a)
29
30#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
31#define bugp(...) do { fprintf(stderr, __VA_ARGS__); perror(" "); exit(1); } while(0)
32
33#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
34
35extern bool g_debug;
36
37typedef struct crypto_key_t *key_array_t;
38int g_nr_keys;
39key_array_t g_key_array;
40
41void *memdup(const void *p, size_t len);
42void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt);
43void generate_random_data(void *buf, size_t sz);
44void *xmalloc(size_t s);
45int convxdigit(char digit, byte *val);
46void print_hex(byte *data, int len, bool newline);
47void add_keys(key_array_t ka, int kac);
48bool parse_key(char **str, struct crypto_key_t *key);
49bool add_keys_from_file(const char *key_file);
50void print_key(struct crypto_key_t *key, bool newline);
51void clear_keys();
52
53typedef char color_t[];
54
55extern color_t OFF, GREY, RED, GREEN, YELLOW, BLUE;
56void color(color_t c);
57void enable_color(bool enable);
58
59#endif /* __MISC_H__ */
diff --git a/utils/imxtools/sbtools/sb.c b/utils/imxtools/sbtools/sb.c
new file mode 100644
index 0000000000..9b97509491
--- /dev/null
+++ b/utils/imxtools/sbtools/sb.c
@@ -0,0 +1,1224 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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 <stdio.h>
22#include <time.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include "misc.h"
26#include "crypto.h"
27#include "sb.h"
28
29static void fill_gaps(struct sb_file_t *sb)
30{
31 for(int i = 0; i < sb->nr_sections; i++)
32 {
33 struct sb_section_t *sec = &sb->sections[i];
34 for(int j = 0; j < sec->nr_insts; j++)
35 {
36 struct sb_inst_t *inst = &sec->insts[j];
37 if(inst->inst != SB_INST_LOAD)
38 continue;
39 inst->padding_size = ROUND_UP(inst->size, BLOCK_SIZE) - inst->size;
40 /* emulate elftosb2 behaviour: generate 15 bytes (that's a safe maximum) */
41 inst->padding = xmalloc(15);
42 generate_random_data(inst->padding, 15);
43 }
44 }
45}
46
47static void compute_sb_offsets(struct sb_file_t *sb)
48{
49 sb->image_size = 0;
50 /* sb header */
51 sb->image_size += sizeof(struct sb_header_t) / BLOCK_SIZE;
52 /* sections headers */
53 sb->image_size += sb->nr_sections * sizeof(struct sb_section_header_t) / BLOCK_SIZE;
54 /* key dictionary */
55 sb->image_size += g_nr_keys * sizeof(struct sb_key_dictionary_entry_t) / BLOCK_SIZE;
56 /* sections */
57 for(int i = 0; i < sb->nr_sections; i++)
58 {
59 /* each section has a preliminary TAG command */
60 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
61 /* we might need to pad the section so compute next alignment */
62 uint32_t alignment = BLOCK_SIZE;
63 if((i + 1) < sb->nr_sections)
64 alignment = sb->sections[i + 1].alignment;
65 alignment /= BLOCK_SIZE; /* alignment in block sizes */
66
67 struct sb_section_t *sec = &sb->sections[i];
68 sec->sec_size = 0;
69
70 if(g_debug)
71 {
72 printf("%s section 0x%08x", sec->is_data ? "Data" : "Boot",
73 sec->identifier);
74 if(sec->is_cleartext)
75 printf(" (cleartext)");
76 printf("\n");
77 }
78
79 sec->file_offset = sb->image_size;
80 for(int j = 0; j < sec->nr_insts; j++)
81 {
82 struct sb_inst_t *inst = &sec->insts[j];
83 if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP)
84 {
85 if(g_debug)
86 printf(" %s | addr=0x%08x | arg=0x%08x\n",
87 inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, inst->argument);
88 sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
89 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
90 }
91 else if(inst->inst == SB_INST_FILL)
92 {
93 if(g_debug)
94 printf(" FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
95 inst->addr, inst->size, inst->pattern);
96 sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
97 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
98 }
99 else if(inst->inst == SB_INST_LOAD)
100 {
101 if(g_debug)
102 printf(" LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size);
103 /* load header */
104 sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
105 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
106 /* data + alignment */
107 sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
108 sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
109 }
110 else if(inst->inst == SB_INST_MODE)
111 {
112 if(g_debug)
113 printf(" MODE | mod=0x%08x\n", inst->addr);
114 sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
115 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
116 }
117 else if(inst->inst == SB_INST_DATA)
118 {
119 if(g_debug)
120 printf(" DATA | size=0x%08x\n", inst->size);
121 sb->image_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
122 sec->sec_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
123 }
124 else
125 {
126 if(g_debug)
127 printf("die on inst %d\n", inst->inst);
128 }
129 }
130 /* we need to make sure next section starts on the right alignment.
131 * Since each section starts with a boot tag, we thus need to ensure
132 * that this sections ends at adress X such that X+BLOCK_SIZE is
133 * a multiple of the alignment.
134 * For data sections, we just add random data, otherwise we add nops */
135 uint32_t missing_sz = alignment - ((sb->image_size + 1) % alignment);
136 if(missing_sz != alignment)
137 {
138 struct sb_inst_t *aug_insts;
139 int nr_aug_insts = 0;
140
141 if(sb->sections[i].is_data)
142 {
143 nr_aug_insts = 1;
144 aug_insts = xmalloc(sizeof(struct sb_inst_t));
145 memset(aug_insts, 0, sizeof(struct sb_inst_t));
146 aug_insts[0].inst = SB_INST_DATA;
147 aug_insts[0].size = missing_sz * BLOCK_SIZE;
148 aug_insts[0].data = xmalloc(missing_sz * BLOCK_SIZE);
149 generate_random_data(aug_insts[0].data, missing_sz * BLOCK_SIZE);
150 if(g_debug)
151 printf(" DATA | size=0x%08x\n", aug_insts[0].size);
152 }
153 else
154 {
155 nr_aug_insts = missing_sz;
156 aug_insts = xmalloc(sizeof(struct sb_inst_t) * nr_aug_insts);
157 memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts);
158 for(int j = 0; j < nr_aug_insts; j++)
159 {
160 aug_insts[j].inst = SB_INST_NOP;
161 if(g_debug)
162 printf(" NOOP\n");
163 }
164 }
165
166 sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t),
167 sb->sections[i].nr_insts, aug_insts, nr_aug_insts);
168 sb->sections[i].nr_insts += nr_aug_insts;
169 free(aug_insts);
170
171 /* augment image and section size */
172 sb->image_size += missing_sz;
173 sec->sec_size += missing_sz;
174 }
175 }
176 /* final signature */
177 sb->image_size += 2;
178}
179
180static uint64_t generate_timestamp()
181{
182 struct tm tm_base;
183 memset(&tm_base, 0, sizeof(tm_base));
184 /* 2000/1/1 0:00:00 */
185 tm_base.tm_mday = 1;
186 tm_base.tm_year = 100;
187 time_t t = time(NULL) - mktime(&tm_base);
188 return (uint64_t)t * 1000000L;
189}
190
191static uint16_t swap16(uint16_t t)
192{
193 return (t << 8) | (t >> 8);
194}
195
196static void fix_version(struct sb_version_t *ver)
197{
198 ver->major = swap16(ver->major);
199 ver->minor = swap16(ver->minor);
200 ver->revision = swap16(ver->revision);
201}
202
203static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
204{
205 struct sha_1_params_t sha_1_params;
206
207 sb_hdr->signature[0] = 'S';
208 sb_hdr->signature[1] = 'T';
209 sb_hdr->signature[2] = 'M';
210 sb_hdr->signature[3] = 'P';
211 sb_hdr->major_ver = IMAGE_MAJOR_VERSION;
212 sb_hdr->minor_ver = IMAGE_MINOR_VERSION;
213 sb_hdr->flags = 0;
214 sb_hdr->image_size = sb->image_size;
215 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE;
216 sb_hdr->first_boot_sec_id = sb->first_boot_sec_id;
217 sb_hdr->nr_keys = g_nr_keys;
218 sb_hdr->nr_sections = sb->nr_sections;
219 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE;
220 sb_hdr->key_dict_off = sb_hdr->header_size +
221 sb_hdr->sec_hdr_size * sb_hdr->nr_sections;
222 sb_hdr->first_boot_tag_off = sb_hdr->key_dict_off +
223 sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE;
224 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0));
225 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1));
226 /* Version 1.0 has 6 bytes of random padding,
227 * Version 1.1 requires the last 4 bytes to be 'sgtl' */
228 if(sb->minor_version >= 1)
229 memcpy(&sb_hdr->rand_pad0[2], "sgtl", 4);
230
231 sb_hdr->timestamp = generate_timestamp();
232 sb_hdr->product_ver = sb->product_ver;
233 fix_version(&sb_hdr->product_ver);
234 sb_hdr->component_ver = sb->component_ver;
235 fix_version(&sb_hdr->component_ver);
236 sb_hdr->drive_tag = sb->drive_tag;
237
238 sha_1_init(&sha_1_params);
239 sha_1_update(&sha_1_params, &sb_hdr->signature[0],
240 sizeof(struct sb_header_t) - sizeof(sb_hdr->sha1_header));
241 sha_1_finish(&sha_1_params);
242 sha_1_output(&sha_1_params, sb_hdr->sha1_header);
243}
244
245static void produce_sb_section_header(struct sb_section_t *sec,
246 struct sb_section_header_t *sec_hdr)
247{
248 sec_hdr->identifier = sec->identifier;
249 sec_hdr->offset = sec->file_offset;
250 sec_hdr->size = sec->sec_size;
251 sec_hdr->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
252 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
253}
254
255static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
256{
257 uint8_t sum = 90;
258 byte *ptr = (byte *)hdr;
259 for(int i = 1; i < 16; i++)
260 sum += ptr[i];
261 return sum;
262}
263
264static void produce_section_tag_cmd(struct sb_section_t *sec,
265 struct sb_instruction_tag_t *tag, bool is_last)
266{
267 tag->hdr.opcode = SB_INST_TAG;
268 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0;
269 tag->identifier = sec->identifier;
270 tag->len = sec->sec_size;
271 tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
272 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
273 tag->hdr.checksum = instruction_checksum(&tag->hdr);
274}
275
276void produce_sb_instruction(struct sb_inst_t *inst,
277 struct sb_instruction_common_t *cmd)
278{
279 memset(cmd, 0, sizeof(struct sb_instruction_common_t));
280 cmd->hdr.opcode = inst->inst;
281 switch(inst->inst)
282 {
283 case SB_INST_CALL:
284 case SB_INST_JUMP:
285 cmd->addr = inst->addr;
286 cmd->data = inst->argument;
287 break;
288 case SB_INST_FILL:
289 cmd->addr = inst->addr;
290 cmd->len = inst->size;
291 cmd->data = inst->pattern;
292 break;
293 case SB_INST_LOAD:
294 cmd->addr = inst->addr;
295 cmd->len = inst->size;
296 cmd->data = crc_continue(crc(inst->data, inst->size),
297 inst->padding, inst->padding_size);
298 break;
299 case SB_INST_MODE:
300 cmd->data = inst->addr;
301 break;
302 case SB_INST_NOP:
303 break;
304 default:
305 if(g_debug)
306 printf("die on invalid inst %d\n", inst->inst);
307 }
308 cmd->hdr.checksum = instruction_checksum(&cmd->hdr);
309}
310
311enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename)
312{
313 struct crypto_key_t real_key;
314 real_key.method = CRYPTO_KEY;
315 byte crypto_iv[16];
316 byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
317 /* init CBC-MACs */
318 for(int i = 0; i < g_nr_keys; i++)
319 memset(cbc_macs[i], 0, 16);
320
321 fill_gaps(sb);
322 compute_sb_offsets(sb);
323
324 generate_random_data(real_key.u.key, 16);
325
326 /* global SHA-1 */
327 struct sha_1_params_t file_sha1;
328 sha_1_init(&file_sha1);
329 /* produce and write header */
330 struct sb_header_t sb_hdr;
331 produce_sb_header(sb, &sb_hdr);
332 /* allocate image */
333 byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE);
334 byte *buf_p = buf;
335 #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0)
336
337 sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr));
338 write(&sb_hdr, sizeof(sb_hdr));
339
340 memcpy(crypto_iv, &sb_hdr, 16);
341
342 /* update CBC-MACs */
343 for(int i = 0; i < g_nr_keys; i++)
344 crypto_cbc((byte *)&sb_hdr, NULL, sizeof(sb_hdr) / BLOCK_SIZE, &g_key_array[i],
345 cbc_macs[i], &cbc_macs[i], 1);
346
347 /* produce and write section headers */
348 for(int i = 0; i < sb_hdr.nr_sections; i++)
349 {
350 struct sb_section_header_t sb_sec_hdr;
351 produce_sb_section_header(&sb->sections[i], &sb_sec_hdr);
352 sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr));
353 write(&sb_sec_hdr, sizeof(sb_sec_hdr));
354 /* update CBC-MACs */
355 for(int j = 0; j < g_nr_keys; j++)
356 crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE,
357 &g_key_array[j], cbc_macs[j], &cbc_macs[j], 1);
358 }
359 /* produce key dictionary */
360 for(int i = 0; i < g_nr_keys; i++)
361 {
362 struct sb_key_dictionary_entry_t entry;
363 memcpy(entry.hdr_cbc_mac, cbc_macs[i], 16);
364 crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i],
365 crypto_iv, NULL, 1);
366
367 write(&entry, sizeof(entry));
368 sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
369 }
370
371 free(cbc_macs);
372
373 /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */
374 /* Image crafting, don't use it unless you understand what you do */
375 if(sb->override_real_key)
376 memcpy(real_key.u.key, sb->real_key, 16);
377 if(sb->override_crypto_iv)
378 memcpy(crypto_iv, sb->crypto_iv, 16);
379 /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */
380 if(g_debug)
381 {
382 printf("Real key: ");
383 for(int j = 0; j < 16; j++)
384 printf("%02x", real_key.u.key[j]);
385 printf("\n");
386 printf("IV : ");
387 for(int j = 0; j < 16; j++)
388 printf("%02x", crypto_iv[j]);
389 printf("\n");
390 }
391 /* produce sections data */
392 for(int i = 0; i< sb_hdr.nr_sections; i++)
393 {
394 /* produce tag command */
395 struct sb_instruction_tag_t tag_cmd;
396 produce_section_tag_cmd(&sb->sections[i], &tag_cmd, (i + 1) == sb_hdr.nr_sections);
397 if(g_nr_keys > 0)
398 crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE,
399 &real_key, crypto_iv, NULL, 1);
400 sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd));
401 write(&tag_cmd, sizeof(tag_cmd));
402 /* produce other commands */
403 byte cur_cbc_mac[16];
404 memcpy(cur_cbc_mac, crypto_iv, 16);
405 for(int j = 0; j < sb->sections[i].nr_insts; j++)
406 {
407 struct sb_inst_t *inst = &sb->sections[i].insts[j];
408 /* command */
409 if(inst->inst != SB_INST_DATA)
410 {
411 struct sb_instruction_common_t cmd;
412 produce_sb_instruction(inst, &cmd);
413 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
414 crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
415 &real_key, cur_cbc_mac, &cur_cbc_mac, 1);
416 sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
417 write(&cmd, sizeof(cmd));
418 }
419 /* data */
420 if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
421 {
422 uint32_t sz = inst->size + inst->padding_size;
423 byte *data = xmalloc(sz);
424 memcpy(data, inst->data, inst->size);
425 memcpy(data + inst->size, inst->padding, inst->padding_size);
426 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
427 crypto_cbc(data, data, sz / BLOCK_SIZE,
428 &real_key, cur_cbc_mac, &cur_cbc_mac, 1);
429 sha_1_update(&file_sha1, data, sz);
430 write(data, sz);
431 free(data);
432 }
433 }
434 }
435 /* write file SHA-1 */
436 byte final_sig[32];
437 sha_1_finish(&file_sha1);
438 sha_1_output(&file_sha1, final_sig);
439 generate_random_data(final_sig + 20, 12);
440 if(g_nr_keys > 0)
441 crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1);
442 write(final_sig, 32);
443
444 if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE)
445 {
446 if(g_debug)
447 printf("SB image buffer was not entirely filled !");
448 return SB_ERROR;
449 }
450
451 FILE *fd = fopen(filename, "wb");
452 if(fd == NULL)
453 return SB_OPEN_ERROR;
454 if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1)
455 {
456 free(buf);
457 return SB_WRITE_ERROR;
458 }
459 fclose(fd);
460 free(buf);
461
462 return SB_SUCCESS;
463}
464
465static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
466 int size, const char *indent, void *u, sb_color_printf cprintf, enum sb_error_t *err)
467{
468 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
469 #define fatal(e, ...) \
470 do { if(err) *err = e; \
471 cprintf(u, true, GREY, __VA_ARGS__); \
472 sb_free_section(*sec); \
473 free(sec); \
474 return NULL; } while(0)
475
476 struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t));
477 memset(sec, 0, sizeof(struct sb_section_t));
478 sec->identifier = id;
479 sec->is_data = data_sec;
480 sec->sec_size = ROUND_UP(size, BLOCK_SIZE) / BLOCK_SIZE;
481
482 if(data_sec)
483 {
484 sec->nr_insts = 1;
485 sec->insts = xmalloc(sizeof(struct sb_inst_t));
486 memset(sec->insts, 0, sizeof(struct sb_inst_t));
487 sec->insts->inst = SB_INST_DATA;
488 sec->insts->size = size;
489 sec->insts->data = memdup(buf, size);
490 return sec;
491 }
492
493 /* Pretty print the content */
494 int pos = 0;
495 while(pos < size)
496 {
497 struct sb_inst_t inst;
498 memset(&inst, 0, sizeof(inst));
499
500 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)&buf[pos];
501 inst.inst = hdr->opcode;
502
503 printf(OFF, "%s", indent);
504 uint8_t checksum = instruction_checksum(hdr);
505 if(checksum != hdr->checksum)
506 fatal(SB_CHECKSUM_ERROR, "Bad instruction checksum");
507 if(hdr->flags != 0)
508 {
509 printf(GREY, "[");
510 printf(BLUE, "f=%x", hdr->flags);
511 printf(GREY, "] ");
512 }
513 if(hdr->opcode == SB_INST_LOAD)
514 {
515 struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos];
516 inst.size = load->len;
517 inst.addr = load->addr;
518 inst.data = memdup(load + 1, load->len);
519
520 printf(RED, "LOAD");
521 printf(OFF, " | ");
522 printf(BLUE, "addr=0x%08x", load->addr);
523 printf(OFF, " | ");
524 printf(GREEN, "len=0x%08x", load->len);
525 printf(OFF, " | ");
526 printf(YELLOW, "crc=0x%08x", load->crc);
527 /* data is padded to 16-byte boundary with random data and crc'ed with it */
528 uint32_t computed_crc = crc(&buf[pos + sizeof(struct sb_instruction_load_t)],
529 ROUND_UP(load->len, 16));
530 if(load->crc == computed_crc)
531 printf(RED, " Ok\n");
532 else
533 {
534 printf(RED, " Failed (crc=0x%08x)\n", computed_crc);
535 fatal(SB_CHECKSUM_ERROR, "Instruction data crc error\n");
536 }
537
538 pos += load->len + sizeof(struct sb_instruction_load_t);
539 }
540 else if(hdr->opcode == SB_INST_FILL)
541 {
542 struct sb_instruction_fill_t *fill = (struct sb_instruction_fill_t *)&buf[pos];
543 inst.pattern = fill->pattern;
544 inst.size = fill->len;
545 inst.addr = fill->addr;
546
547 printf(RED, "FILL");
548 printf(OFF, " | ");
549 printf(BLUE, "addr=0x%08x", fill->addr);
550 printf(OFF, " | ");
551 printf(GREEN, "len=0x%08x", fill->len);
552 printf(OFF, " | ");
553 printf(YELLOW, "pattern=0x%08x\n", fill->pattern);
554
555 pos += sizeof(struct sb_instruction_fill_t);
556 }
557 else if(hdr->opcode == SB_INST_CALL ||
558 hdr->opcode == SB_INST_JUMP)
559 {
560 int is_call = (hdr->opcode == SB_INST_CALL);
561 struct sb_instruction_call_t *call = (struct sb_instruction_call_t *)&buf[pos];
562 inst.addr = call->addr;
563 inst.argument = call->arg;
564
565 if(is_call)
566 printf(RED, "CALL");
567 else
568 printf(RED, "JUMP");
569 printf(OFF, " | ");
570 printf(BLUE, "addr=0x%08x", call->addr);
571 printf(OFF, " | ");
572 printf(GREEN, "arg=0x%08x\n", call->arg);
573
574 pos += sizeof(struct sb_instruction_call_t);
575 }
576 else if(hdr->opcode == SB_INST_MODE)
577 {
578 struct sb_instruction_mode_t *mode = (struct sb_instruction_mode_t *)hdr;
579 inst.argument = mode->mode;
580
581 printf(RED, "MODE");
582 printf(OFF, " | ");
583 printf(BLUE, "mod=0x%08x\n", mode->mode);
584
585 pos += sizeof(struct sb_instruction_mode_t);
586 }
587 else if(hdr->opcode == SB_INST_NOP)
588 {
589 printf(RED, "NOOP\n");
590 pos += sizeof(struct sb_instruction_mode_t);
591 }
592 else
593 {
594 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
595 break;
596 }
597
598 sec->insts = augment_array(sec->insts, sizeof(struct sb_inst_t), sec->nr_insts++, &inst, 1);
599 pos = ROUND_UP(pos, BLOCK_SIZE);
600 }
601
602 return sec;
603 #undef printf
604 #undef fatal
605}
606
607void sb_fill_section_name(char name[5], uint32_t identifier)
608{
609 name[0] = (identifier >> 24) & 0xff;
610 name[1] = (identifier >> 16) & 0xff;
611 name[2] = (identifier >> 8) & 0xff;
612 name[3] = identifier & 0xff;
613 for(int i = 0; i < 4; i++)
614 if(!isprint(name[i]))
615 name[i] = '_';
616 name[4] = 0;
617}
618
619static uint32_t guess_alignment(uint32_t off)
620{
621 /* find greatest power of two which divides the offset */
622 if(off == 0)
623 return 1;
624 uint32_t a = 1;
625 while(off % (2 * a) == 0)
626 a *= 2;
627 return a;
628}
629
630struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
631 sb_color_printf cprintf, enum sb_error_t *err)
632{
633 return sb_read_file_ex(filename, 0, -1, raw_mode, u, cprintf, err);
634}
635
636struct sb_file_t *sb_read_file_ex(const char *filename, size_t offset, size_t size, bool raw_mode, void *u,
637 sb_color_printf cprintf, enum sb_error_t *err)
638{
639 #define fatal(e, ...) \
640 do { if(err) *err = e; \
641 cprintf(u, true, GREY, __VA_ARGS__); \
642 free(buf); \
643 return NULL; } while(0)
644
645 FILE *f = fopen(filename, "rb");
646 void *buf = NULL;
647 if(f == NULL)
648 fatal(SB_OPEN_ERROR, "Cannot open file for reading\n");
649 fseek(f, 0, SEEK_END);
650 size_t read_size = ftell(f);
651 fseek(f, offset, SEEK_SET);
652 if(size != (size_t)-1)
653 read_size = size;
654 buf = xmalloc(read_size);
655 if(fread(buf, read_size, 1, f) != 1)
656 {
657 fclose(f);
658 fatal(SB_READ_ERROR, "Cannot read file\n");
659 }
660 fclose(f);
661
662 struct sb_file_t *ret = sb_read_memory(buf, read_size, raw_mode, u, cprintf, err);
663 free(buf);
664 return ret;
665
666 #undef fatal
667}
668
669struct sb_file_t *sb_read_memory(void *_buf, size_t filesize, bool raw_mode, void *u,
670 sb_color_printf cprintf, enum sb_error_t *err)
671{
672 struct sb_file_t *sb_file = NULL;
673 uint8_t *buf = _buf;
674
675 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
676 #define fatal(e, ...) \
677 do { if(err) *err = e; \
678 cprintf(u, true, GREY, __VA_ARGS__); \
679 sb_free(sb_file); \
680 return NULL; } while(0)
681 #define print_hex(c, p, len, nl) \
682 do { printf(c, ""); print_hex(p, len, nl); } while(0)
683
684 struct sha_1_params_t sha_1_params;
685 sb_file = xmalloc(sizeof(struct sb_file_t));
686 memset(sb_file, 0, sizeof(struct sb_file_t));
687 struct sb_header_t *sb_header = (struct sb_header_t *)buf;
688
689 sb_file->image_size = sb_header->image_size;
690 sb_file->minor_version = sb_header->minor_ver;
691 sb_file->flags = sb_header->flags;
692 sb_file->drive_tag = sb_header->drive_tag;
693 sb_file->first_boot_sec_id = sb_header->first_boot_sec_id;
694
695 if(memcmp(sb_header->signature, "STMP", 4) != 0)
696 fatal(SB_FORMAT_ERROR, "Bad signature\n");
697 if(sb_header->image_size * BLOCK_SIZE > filesize)
698 fatal(SB_FORMAT_ERROR, "File too small (should be at least %d bytes)\n",
699 sb_header->image_size * BLOCK_SIZE);
700 if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
701 fatal(SB_FORMAT_ERROR, "Bad header size\n");
702 if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
703 fatal(SB_FORMAT_ERROR, "Bad section header size\n");
704
705 if(filesize > sb_header->image_size * BLOCK_SIZE)
706 {
707 printf(GREY, "[Restrict file size from %lu to %d bytes]\n", filesize,
708 sb_header->image_size * BLOCK_SIZE);
709 filesize = sb_header->image_size * BLOCK_SIZE;
710 }
711
712 printf(BLUE, "Basic info:\n");
713 printf(GREEN, " SB version: ");
714 printf(YELLOW, "%d.%d\n", sb_header->major_ver, sb_header->minor_ver);
715 printf(GREEN, " Header SHA-1: ");
716 byte *hdr_sha1 = sb_header->sha1_header;
717 print_hex(YELLOW, hdr_sha1, 20, false);
718 /* Check SHA1 sum */
719 byte computed_sha1[20];
720 sha_1_init(&sha_1_params);
721 sha_1_update(&sha_1_params, &sb_header->signature[0],
722 sizeof(struct sb_header_t) - sizeof(sb_header->sha1_header));
723 sha_1_finish(&sha_1_params);
724 sha_1_output(&sha_1_params, computed_sha1);
725 if(memcmp(hdr_sha1, computed_sha1, 20) == 0)
726 printf(RED, " Ok\n");
727 else
728 printf(RED, " Failed\n");
729 printf(GREEN, " Flags: ");
730 printf(YELLOW, "%x\n", sb_header->flags);
731 printf(GREEN, " Total file size : ");
732 printf(YELLOW, "%ld\n", filesize);
733
734 /* Sizes and offsets */
735 printf(BLUE, "Sizes and offsets:\n");
736 printf(GREEN, " # of encryption keys = ");
737 printf(YELLOW, "%d\n", sb_header->nr_keys);
738 printf(GREEN, " # of sections = ");
739 printf(YELLOW, "%d\n", sb_header->nr_sections);
740
741 /* Versions */
742 printf(BLUE, "Versions\n");
743
744 printf(GREEN, " Random 1: ");
745 print_hex(YELLOW, sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
746 printf(GREEN, " Random 2: ");
747 print_hex(YELLOW, sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
748
749 uint64_t micros = sb_header->timestamp;
750 time_t seconds = (micros / (uint64_t)1000000L);
751 struct tm tm_base;
752 memset(&tm_base, 0, sizeof(tm_base));
753 /* 2000/1/1 0:00:00 */
754 tm_base.tm_mday = 1;
755 tm_base.tm_year = 100;
756 seconds += mktime(&tm_base);
757 struct tm *time = gmtime(&seconds);
758 printf(GREEN, " Creation date/time = ");
759 printf(YELLOW, "%s", asctime(time));
760
761 struct sb_version_t product_ver = sb_header->product_ver;
762 fix_version(&product_ver);
763 struct sb_version_t component_ver = sb_header->component_ver;
764 fix_version(&component_ver);
765
766 memcpy(&sb_file->product_ver, &product_ver, sizeof(product_ver));
767 memcpy(&sb_file->component_ver, &component_ver, sizeof(component_ver));
768
769 printf(GREEN, " Product version = ");
770 printf(YELLOW, "%X.%X.%X\n", product_ver.major, product_ver.minor, product_ver.revision);
771 printf(GREEN, " Component version = ");
772 printf(YELLOW, "%X.%X.%X\n", component_ver.major, component_ver.minor, component_ver.revision);
773
774 printf(GREEN, " Drive tag = ");
775 printf(YELLOW, "%x\n", sb_header->drive_tag);
776 printf(GREEN, " First boot tag offset = ");
777 printf(YELLOW, "%x\n", sb_header->first_boot_tag_off);
778 printf(GREEN, " First boot section ID = ");
779 printf(YELLOW, "0x%08x\n", sb_header->first_boot_sec_id);
780
781 /* encryption cbc-mac */
782 byte real_key[16];
783 bool valid_key = false; /* false until a matching key was found */
784
785 if(sb_header->nr_keys > 0)
786 {
787 byte (*cbcmacs)[16] = xmalloc(16 * g_nr_keys);
788 printf(BLUE, "Encryption keys\n");
789 for(int i = 0; i < g_nr_keys; i++)
790 {
791 printf(RED, " Key %d: ", i);
792 printf(YELLOW, "");
793 print_key(&g_key_array[i], true);
794 printf(GREEN, " CBC-MAC: ");
795 /* check it */
796 byte zero[16];
797 memset(zero, 0, 16);
798 int ret = crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections,
799 &g_key_array[i], zero, &cbcmacs[i], 1);
800 if(ret != CRYPTO_ERROR_SUCCESS)
801 {
802 free(cbcmacs);
803 fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d", ret);
804 }
805 print_hex(YELLOW, cbcmacs[i], 16, true);
806 }
807
808 printf(BLUE, "DEK\n");
809 for(int i = 0; i < sb_header->nr_keys; i++)
810 {
811 printf(RED, " Entry %d\n", i);
812 uint32_t ofs = sizeof(struct sb_header_t)
813 + sizeof(struct sb_section_header_t) * sb_header->nr_sections
814 + sizeof(struct sb_key_dictionary_entry_t) * i;
815 struct sb_key_dictionary_entry_t *dict_entry =
816 (struct sb_key_dictionary_entry_t *)&buf[ofs];
817 /* cbc mac */
818 printf(GREEN, " Encrypted key: ");
819 print_hex(YELLOW, dict_entry->key, 16, true);
820 printf(GREEN, " CBC-MAC : ");
821 print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false);
822 /* check it */
823 int idx = 0;
824 while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0)
825 idx++;
826 if(idx != g_nr_keys)
827 {
828 printf(RED, " Match\n");
829 /* decrypt */
830 byte decrypted_key[16];
831 byte iv[16];
832 memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
833 int ret = crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[idx], iv, NULL, 0);
834 if(ret != CRYPTO_ERROR_SUCCESS)
835 {
836 free(cbcmacs);
837 fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d\n", ret);
838 }
839 printf(GREEN, " Decrypted key: ");
840 print_hex(YELLOW, decrypted_key, 16, false);
841 if(valid_key)
842 {
843 if(memcmp(real_key, decrypted_key, 16) == 0)
844 printf(RED, " Cross-Check Ok");
845 else
846 printf(RED, " Cross-Check Failed");
847 }
848 else
849 {
850 memcpy(real_key, decrypted_key, 16);
851 valid_key = true;
852 }
853 printf(OFF, "\n");
854 }
855 else
856 printf(RED, " Don't Match\n");
857 }
858
859 free(cbcmacs);
860
861 if(!valid_key)
862 fatal(SB_NO_VALID_KEY, "No valid key found\n");
863
864 if(getenv("SB_REAL_KEY") != 0)
865 {
866 struct crypto_key_t k;
867 char *env = getenv("SB_REAL_KEY");
868 if(!parse_key(&env, &k) || *env)
869 fatal(SB_ERROR, "Invalid SB_REAL_KEY\n");
870 memcpy(real_key, k.u.key, 16);
871 }
872
873 printf(RED, " Summary:\n");
874 printf(GREEN, " Real key: ");
875 print_hex(YELLOW, real_key, 16, true);
876 printf(GREEN, " IV : ");
877 print_hex(YELLOW, buf, 16, true);
878
879 sb_file->override_real_key = true;
880 memcpy(sb_file->real_key, real_key, 16);
881 sb_file->override_crypto_iv = true;
882 memcpy(sb_file->crypto_iv, buf, 16);
883 }
884
885 /* sections */
886 if(!raw_mode)
887 {
888 sb_file->nr_sections = sb_header->nr_sections;
889 sb_file->sections = xmalloc(sb_file->nr_sections * sizeof(struct sb_section_t));
890 memset(sb_file->sections, 0, sb_file->nr_sections * sizeof(struct sb_section_t));
891 printf(BLUE, "Sections\n");
892 for(int i = 0; i < sb_header->nr_sections; i++)
893 {
894 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
895 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&buf[ofs];
896
897 char name[5];
898 sb_fill_section_name(name, sec_hdr->identifier);
899 int pos = sec_hdr->offset * BLOCK_SIZE;
900 int size = sec_hdr->size * BLOCK_SIZE;
901 int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
902 int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
903
904 printf(GREEN, " Section ");
905 printf(YELLOW, "'%s'\n", name);
906 printf(GREEN, " pos = ");
907 printf(YELLOW, "%8x - %8x\n", pos, pos+size);
908 printf(GREEN, " len = ");
909 printf(YELLOW, "%8x\n", size);
910 printf(GREEN, " flags = ");
911 printf(YELLOW, "%8x", sec_hdr->flags);
912 if(data_sec)
913 printf(RED, " Data Section");
914 else
915 printf(RED, " Boot Section");
916 if(encrypted)
917 printf(RED, " (Encrypted)");
918 printf(OFF, "\n");
919
920 /* save it */
921 byte *sec = xmalloc(size);
922 if(encrypted)
923 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
924 else
925 memcpy(sec, buf + pos, size);
926
927 struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier,
928 sec, size, " ", u, cprintf, err);
929 if(s)
930 {
931 s->is_cleartext = !encrypted;
932 s->alignment = guess_alignment(pos);
933 memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
934 free(s);
935 }
936 else
937 fatal(*err, "Error reading section\n");
938
939 free(sec);
940 }
941 }
942 else
943 {
944 /* advanced raw mode */
945 printf(BLUE, "Commands\n");
946 uint32_t offset = sb_header->first_boot_tag_off * BLOCK_SIZE;
947 byte iv[16];
948 const char *indent = " ";
949 while(true)
950 {
951 /* restart with IV */
952 memcpy(iv, buf, 16);
953 byte cmd[BLOCK_SIZE];
954 if(sb_header->nr_keys > 0)
955 cbc_mac(buf + offset, cmd, 1, real_key, iv, &iv, 0);
956 else
957 memcpy(cmd, buf + offset, BLOCK_SIZE);
958 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)cmd;
959 printf(OFF, "%s", indent);
960 uint8_t checksum = instruction_checksum(hdr);
961 if(checksum != hdr->checksum)
962 printf(GREY, "[Bad checksum']");
963
964 if(hdr->opcode == SB_INST_NOP)
965 {
966 printf(RED, "NOOP\n");
967 offset += BLOCK_SIZE;
968 }
969 else if(hdr->opcode == SB_INST_TAG)
970 {
971 struct sb_instruction_tag_t *tag = (struct sb_instruction_tag_t *)hdr;
972 printf(RED, "BTAG");
973 printf(OFF, " | ");
974 printf(BLUE, "sec=0x%08x", tag->identifier);
975 printf(OFF, " | ");
976 printf(GREEN, "cnt=0x%08x", tag->len);
977 printf(OFF, " | ");
978 printf(YELLOW, "flg=0x%08x", tag->flags);
979 if(tag->hdr.flags & SB_INST_LAST_TAG)
980 {
981 printf(OFF, " | ");
982 printf(RED, " Last section");
983 }
984 printf(OFF, "\n");
985 offset += sizeof(struct sb_instruction_tag_t);
986
987 char name[5];
988 sb_fill_section_name(name, tag->identifier);
989 int pos = offset;
990 int size = tag->len * BLOCK_SIZE;
991 int data_sec = !(tag->flags & SECTION_BOOTABLE);
992 int encrypted = !(tag->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
993
994 printf(GREEN, "%sSection ", indent);
995 printf(YELLOW, "'%s'\n", name);
996 printf(GREEN, "%s pos = ", indent);
997 printf(YELLOW, "%8x - %8x\n", pos, pos+size);
998 printf(GREEN, "%s len = ", indent);
999 printf(YELLOW, "%8x\n", size);
1000 printf(GREEN, "%s flags = ", indent);
1001 printf(YELLOW, "%8x", tag->flags);
1002 if(data_sec)
1003 printf(RED, " Data Section");
1004 else
1005 printf(RED, " Boot Section");
1006 if(encrypted)
1007 printf(RED, " (Encrypted)");
1008 printf(OFF, "\n");
1009
1010 /* save it */
1011 byte *sec = xmalloc(size);
1012 if(encrypted)
1013 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
1014 else
1015 memcpy(sec, buf + pos, size);
1016
1017 struct sb_section_t *s = read_section(data_sec, tag->identifier,
1018 sec, size, " ", u, cprintf, err);
1019 if(s)
1020 {
1021 s->is_cleartext = !encrypted;
1022 s->alignment = guess_alignment(pos);
1023 sb_file->sections = augment_array(sb_file->sections,
1024 sizeof(struct sb_section_t), sb_file->nr_sections++,
1025 s, 1);
1026 free(s);
1027 }
1028 else
1029 fatal(*err, "Error reading section\n");
1030 free(sec);
1031
1032 /* last one ? */
1033 if(tag->hdr.flags & SB_INST_LAST_TAG)
1034 break;
1035 offset += size;
1036 }
1037 else
1038 {
1039 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
1040 break;
1041 }
1042 }
1043 }
1044
1045 /* final signature */
1046 printf(BLUE, "Final signature:\n");
1047 byte decrypted_block[32];
1048 if(sb_header->nr_keys > 0)
1049 {
1050 printf(GREEN, " Encrypted SHA-1:\n");
1051 byte *encrypted_block = &buf[filesize - 32];
1052 printf(OFF, " ");
1053 print_hex(YELLOW, encrypted_block, 16, true);
1054 printf(OFF, " ");
1055 print_hex(YELLOW, encrypted_block + 16, 16, true);
1056 /* decrypt it */
1057 cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0);
1058 }
1059 else
1060 memcpy(decrypted_block, &buf[filesize - 32], 32);
1061 printf(GREEN, " File SHA-1:\n ");
1062 print_hex(YELLOW, decrypted_block, 20, false);
1063 /* check it */
1064 sha_1_init(&sha_1_params);
1065 sha_1_update(&sha_1_params, buf, filesize - 32);
1066 sha_1_finish(&sha_1_params);
1067 sha_1_output(&sha_1_params, computed_sha1);
1068 if(memcmp(decrypted_block, computed_sha1, 20) == 0)
1069 printf(RED, " Ok\n");
1070 else
1071 {
1072 printf(RED, " Failed\n");
1073 fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n");
1074 }
1075
1076 return sb_file;
1077 #undef printf
1078 #undef fatal
1079 #undef print_hex
1080}
1081
1082void sb_free_instruction(struct sb_inst_t inst)
1083{
1084 free(inst.padding);
1085 free(inst.data);
1086}
1087
1088void sb_free_section(struct sb_section_t sec)
1089{
1090 for(int j = 0; j < sec.nr_insts; j++)
1091 sb_free_instruction(sec.insts[j]);
1092 free(sec.insts);
1093}
1094
1095void sb_free(struct sb_file_t *file)
1096{
1097 if(!file) return;
1098
1099 for(int i = 0; i < file->nr_sections; i++)
1100 sb_free_section(file->sections[i]);
1101
1102 free(file->sections);
1103 free(file);
1104}
1105
1106void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf)
1107{
1108 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
1109 #define print_hex(c, p, len, nl) \
1110 do { printf(c, ""); print_hex(p, len, nl); } while(0)
1111
1112 #define TREE RED
1113 #define HEADER GREEN
1114 #define TEXT YELLOW
1115 #define TEXT2 BLUE
1116 #define SEP OFF
1117
1118 printf(HEADER, "SB File\n");
1119 printf(TREE, "+-");
1120 printf(HEADER, "Version: ");
1121 printf(TEXT, "1.%d\n", file->minor_version);
1122 printf(TREE, "+-");
1123 printf(HEADER, "Flags: ");
1124 printf(TEXT, "%x\n", file->flags);
1125 printf(TREE, "+-");
1126 printf(HEADER, "Drive Tag: ");
1127 printf(TEXT, "%x\n", file->drive_tag);
1128 printf(TREE, "+-");
1129 printf(HEADER, "First Boot Section ID: ");
1130 char name[5];
1131 sb_fill_section_name(name, file->first_boot_sec_id);
1132 printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name);
1133
1134 if(file->override_real_key)
1135 {
1136 printf(TREE, "+-");
1137 printf(HEADER, "Real key: ");
1138 print_hex(TEXT, file->real_key, 16, true);
1139 }
1140 if(file->override_crypto_iv)
1141 {
1142 printf(TREE, "+-");
1143 printf(HEADER, "IV : ");
1144 print_hex(TEXT, file->crypto_iv, 16, true);
1145 }
1146 printf(TREE, "+-");
1147 printf(HEADER, "Product Version: ");
1148 printf(TEXT, "%X.%X.%X\n", file->product_ver.major, file->product_ver.minor,
1149 file->product_ver.revision);
1150 printf(TREE, "+-");
1151 printf(HEADER, "Component Version: ");
1152 printf(TEXT, "%X.%X.%X\n", file->component_ver.major, file->component_ver.minor,
1153 file->component_ver.revision);
1154
1155 for(int i = 0; i < file->nr_sections; i++)
1156 {
1157 struct sb_section_t *sec = &file->sections[i];
1158 printf(TREE, "+-");
1159 printf(HEADER, "Section\n");
1160 printf(TREE,"| +-");
1161 printf(HEADER, "Identifier: ");
1162 sb_fill_section_name(name, sec->identifier);
1163 printf(TEXT, "%08x (%s)\n", sec->identifier, name);
1164 printf(TREE, "| +-");
1165 printf(HEADER, "Type: ");
1166 printf(TEXT, "%s (%s)\n", sec->is_data ? "Data Section" : "Boot Section",
1167 sec->is_cleartext ? "Cleartext" : "Encrypted");
1168 printf(TREE, "| +-");
1169 printf(HEADER, "Alignment: ");
1170 printf(TEXT, "%d (bytes)\n", sec->alignment);
1171 printf(TREE, "| +-");
1172 printf(HEADER, "Instructions\n");
1173 for(int j = 0; j < sec->nr_insts; j++)
1174 {
1175 struct sb_inst_t *inst = &sec->insts[j];
1176 printf(TREE, "| | +-");
1177 switch(inst->inst)
1178 {
1179 case SB_INST_DATA:
1180 printf(HEADER, "DATA");
1181 printf(SEP, " | ");
1182 printf(TEXT, "size=0x%08x\n", inst->size);
1183 break;
1184 case SB_INST_CALL:
1185 case SB_INST_JUMP:
1186 printf(HEADER, "%s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP");
1187 printf(SEP, " | ");
1188 printf(TEXT, "addr=0x%08x", inst->addr);
1189 printf(SEP, " | ");
1190 printf(TEXT2, "arg=0x%08x\n", inst->argument);
1191 break;
1192 case SB_INST_LOAD:
1193 printf(HEADER, "LOAD");
1194 printf(SEP, " | ");
1195 printf(TEXT, "addr=0x%08x", inst->addr);
1196 printf(SEP, " | ");
1197 printf(TEXT2, "len=0x%08x\n", inst->size);
1198 break;
1199 case SB_INST_FILL:
1200 printf(HEADER, "FILL");
1201 printf(SEP, " | ");
1202 printf(TEXT, "addr=0x%08x", inst->addr);
1203 printf(SEP, " | ");
1204 printf(TEXT2, "len=0x%08x", inst->size);
1205 printf(SEP, " | ");
1206 printf(TEXT2, "pattern=0x%08x\n", inst->pattern);
1207 break;
1208 case SB_INST_MODE:
1209 printf(HEADER, "MODE");
1210 printf(SEP, " | ");
1211 printf(TEXT, "mod=0x%08x\n", inst->addr);
1212 break;
1213 case SB_INST_NOP:
1214 printf(HEADER, "NOOP\n");
1215 break;
1216 default:
1217 printf(GREY, "[Unknown instruction %x]\n", inst->inst);
1218 }
1219 }
1220 }
1221
1222 #undef printf
1223 #undef print_hex
1224}
diff --git a/utils/imxtools/sbtools/sb.h b/utils/imxtools/sbtools/sb.h
new file mode 100644
index 0000000000..74d86f303a
--- /dev/null
+++ b/utils/imxtools/sbtools/sb.h
@@ -0,0 +1,243 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 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#ifndef __SB_H__
22#define __SB_H__
23
24#include <stdint.h>
25#include <stdbool.h>
26
27#include "misc.h"
28
29#define BLOCK_SIZE 16
30
31/* All fields are in big-endian BCD */
32struct sb_version_t
33{
34 uint16_t major;
35 uint16_t pad0;
36 uint16_t minor;
37 uint16_t pad1;
38 uint16_t revision;
39 uint16_t pad2;
40};
41
42struct sb_header_t
43{
44 uint8_t sha1_header[20]; /* SHA-1 of the rest of the header */
45 uint8_t signature[4]; /* Signature "STMP" */
46 uint8_t major_ver; /* Should be 1 */
47 uint8_t minor_ver; /* Should be 1 */
48 uint16_t flags;
49 uint32_t image_size; /* In blocks (=16bytes) */
50 uint32_t first_boot_tag_off; /* Offset in blocks */
51 uint32_t first_boot_sec_id; /* First bootable section ID */
52 uint16_t nr_keys; /* Number of encryption keys */
53 uint16_t key_dict_off; /* Offset to key dictionary (in blocks) */
54 uint16_t header_size; /* In blocks */
55 uint16_t nr_sections; /* Number of sections */
56 uint16_t sec_hdr_size; /* Section header size (in blocks) */
57 uint8_t rand_pad0[6]; /* Random padding */
58 uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */
59 struct sb_version_t product_ver;
60 struct sb_version_t component_ver;
61 uint16_t drive_tag; /* first tag to boot ? */
62 uint8_t rand_pad1[6]; /* Random padding */
63} __attribute__((packed));
64
65struct sb_section_header_t
66{
67 uint32_t identifier;
68 uint32_t offset; /* In blocks */
69 uint32_t size; /* In blocks */
70 uint32_t flags;
71} __attribute__((packed));
72
73struct sb_key_dictionary_entry_t
74{
75 uint8_t hdr_cbc_mac[16]; /* CBC-MAC of the header */
76 uint8_t key[16]; /* Actual AES Key (encrypted by the global key) */
77} __attribute__((packed));
78
79#define IMAGE_MAJOR_VERSION 1
80#define IMAGE_MINOR_VERSION 1
81
82#define SECTION_BOOTABLE (1 << 0)
83#define SECTION_CLEARTEXT (1 << 1)
84
85#define SB_INST_NOP 0x0
86#define SB_INST_TAG 0x1
87#define SB_INST_LOAD 0x2
88#define SB_INST_FILL 0x3
89#define SB_INST_JUMP 0x4
90#define SB_INST_CALL 0x5
91#define SB_INST_MODE 0x6
92
93/* flags */
94#define SB_INST_LAST_TAG 1 /* for TAG */
95#define SB_INST_LOAD_DCD 1 /* for LOAD */
96#define SB_INST_FILL_BYTE 0 /* for FILL */
97#define SB_INST_FILL_HWORD 1 /* for FILL */
98#define SB_INST_FILL_WORD 2 /* for FILL */
99#define SB_INST_HAB_EXEC 1 /* for JUMP/CALL */
100
101struct sb_instruction_header_t
102{
103 uint8_t checksum;
104 uint8_t opcode;
105 uint16_t flags;
106} __attribute__((packed));
107
108struct sb_instruction_common_t
109{
110 struct sb_instruction_header_t hdr;
111 uint32_t addr;
112 uint32_t len;
113 uint32_t data;
114} __attribute__((packed));
115
116struct sb_instruction_load_t
117{
118 struct sb_instruction_header_t hdr;
119 uint32_t addr;
120 uint32_t len;
121 uint32_t crc;
122} __attribute__((packed));
123
124struct sb_instruction_fill_t
125{
126 struct sb_instruction_header_t hdr;
127 uint32_t addr;
128 uint32_t len;
129 uint32_t pattern;
130} __attribute__((packed));
131
132struct sb_instruction_mode_t
133{
134 struct sb_instruction_header_t hdr;
135 uint32_t zero1;
136 uint32_t zero2;
137 uint32_t mode;
138} __attribute__((packed));
139
140struct sb_instruction_call_t
141{
142 struct sb_instruction_header_t hdr;
143 uint32_t addr;
144 uint32_t zero;
145 uint32_t arg;
146} __attribute__((packed));
147
148struct sb_instruction_tag_t
149{
150 struct sb_instruction_header_t hdr;
151 uint32_t identifier; /* section identifier */
152 uint32_t len; /* length of the section */
153 uint32_t flags; /* section flags */
154} __attribute__((packed));
155
156/*******
157 * API *
158 *******/
159
160#define SB_INST_DATA 0xff
161
162struct sb_inst_t
163{
164 uint8_t inst; /* SB_INST_* */
165 uint32_t size;
166 uint32_t addr;
167 // <union>
168 void *data;
169 uint32_t pattern;
170 // </union>
171 uint32_t argument; // for call, jump and mode
172 /* for production use */
173 uint32_t padding_size;
174 uint8_t *padding;
175};
176
177struct sb_section_t
178{
179 uint32_t identifier;
180 bool is_data;
181 bool is_cleartext;
182 uint32_t alignment;
183 // data sections are handled as one or more SB_INST_DATA virtual instruction
184 int nr_insts;
185 struct sb_inst_t *insts;
186 /* for production use */
187 uint32_t file_offset; /* in blocks */
188 uint32_t sec_size; /* in blocks */
189};
190
191struct sb_file_t
192{
193 /* override real, otherwise it is randomly generated */
194 bool override_real_key;
195 uint8_t real_key[16];
196 /* override crypto IV, use with caution ! Use NULL to generate it */
197 bool override_crypto_iv;
198 uint8_t crypto_iv[16];
199
200 int nr_sections;
201 uint16_t drive_tag;
202 uint32_t first_boot_sec_id;
203 uint16_t flags;
204 uint8_t minor_version;
205 struct sb_section_t *sections;
206 struct sb_version_t product_ver;
207 struct sb_version_t component_ver;
208 /* for production use */
209 uint32_t image_size; /* in blocks */
210};
211
212enum sb_error_t
213{
214 SB_SUCCESS = 0,
215 SB_ERROR = -1,
216 SB_OPEN_ERROR = -2,
217 SB_READ_ERROR = -3,
218 SB_WRITE_ERROR = -4,
219 SB_FORMAT_ERROR = -5,
220 SB_CHECKSUM_ERROR = -6,
221 SB_NO_VALID_KEY = -7,
222 SB_FIRST_CRYPTO_ERROR = -8,
223 SB_LAST_CRYPTO_ERROR = SB_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS,
224};
225
226enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename);
227
228typedef void (*sb_color_printf)(void *u, bool err, color_t c, const char *f, ...);
229struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
230 sb_color_printf printf, enum sb_error_t *err);
231/* use size_t(-1) to use maximum size */
232struct sb_file_t *sb_read_file_ex(const char *filename, size_t offset, size_t size, bool raw_mode, void *u,
233 sb_color_printf printf, enum sb_error_t *err);
234struct sb_file_t *sb_read_memory(void *buffer, size_t size, bool raw_mode, void *u,
235 sb_color_printf printf, enum sb_error_t *err);
236
237void sb_fill_section_name(char name[5], uint32_t identifier);
238void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf);
239void sb_free_instruction(struct sb_inst_t inst);
240void sb_free_section(struct sb_section_t file);
241void sb_free(struct sb_file_t *file);
242
243#endif /* __SB_H__ */
diff --git a/utils/imxtools/sbtools/sbloader.c b/utils/imxtools/sbtools/sbloader.c
new file mode 100644
index 0000000000..e1534ea7d5
--- /dev/null
+++ b/utils/imxtools/sbtools/sbloader.c
@@ -0,0 +1,193 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <libusb.h>
25#include <stdint.h>
26
27void put32le(uint8_t *buf, uint32_t i)
28{
29 *buf++ = i & 0xff;
30 *buf++ = (i >> 8) & 0xff;
31 *buf++ = (i >> 16) & 0xff;
32 *buf++ = (i >> 24) & 0xff;
33}
34
35void put32be(uint8_t *buf, uint32_t i)
36{
37 *buf++ = (i >> 24) & 0xff;
38 *buf++ = (i >> 16) & 0xff;
39 *buf++ = (i >> 8) & 0xff;
40 *buf++ = i & 0xff;
41}
42
43struct dev_info_t
44{
45 uint16_t vendor_id;
46 uint16_t product_id;
47 unsigned xfer_size;
48};
49
50struct dev_info_t g_dev_info[] =
51{
52 {0x066f, 0x3780, 1024}, /* i.MX233 / STMP3780 */
53 {0x066f, 0x3770, 48}, /* STMP3770 */
54 {0x15A2, 0x004F, 1024}, /* i.MX28 */
55};
56
57int main(int argc, char **argv)
58{
59 int ret;
60 FILE *f;
61 int i, xfer_size, nr_xfers, recv_size;
62
63 if(argc != 3)
64 {
65 printf("usage: %s <xfer size> <file>\n", argv[0]);
66 printf("If <xfer size> is set to zero, the preferred one is used.\n");
67 return 1;
68 }
69
70 char *end;
71 xfer_size = strtol(argv[1], &end, 0);
72 if(end != (argv[1] + strlen(argv[1])))
73 {
74 printf("Invalid transfer size !\n");
75 return 1;
76 }
77
78 libusb_device_handle *dev;
79
80 libusb_init(NULL);
81
82 libusb_set_debug(NULL, 3);
83
84 for(unsigned i = 0; i < sizeof(g_dev_info) / sizeof(g_dev_info[0]); i++)
85 {
86 dev = libusb_open_device_with_vid_pid(NULL,
87 g_dev_info[i].vendor_id, g_dev_info[i].product_id);
88 if(dev == NULL)
89 continue;
90 if(xfer_size == 0)
91 xfer_size = g_dev_info[i].xfer_size;
92 printf("Found a match for %04x:%04x\n",
93 g_dev_info[i].vendor_id, g_dev_info[i].product_id);
94 break;
95 }
96 if(dev == NULL)
97 {
98 printf("Cannot open device\n");
99 return 1;
100 }
101
102 libusb_detach_kernel_driver(dev, 0);
103 libusb_detach_kernel_driver(dev, 4);
104
105 libusb_claim_interface (dev, 0);
106 libusb_claim_interface (dev, 4);
107
108 if(!dev)
109 {
110 printf("No dev\n");
111 exit(1);
112 }
113
114 f = fopen(argv[2], "r");
115 if(f == NULL)
116 {
117 perror("cannot open file");
118 return 1;
119 }
120 fseek(f, 0, SEEK_END);
121 size_t size = ftell(f);
122 fseek(f, 0, SEEK_SET);
123
124 printf("Transfer size: %d\n", xfer_size);
125 nr_xfers = (size + xfer_size - 1) / xfer_size;
126 uint8_t *file_buf = malloc(nr_xfers * xfer_size);
127 memset(file_buf, 0xff, nr_xfers * xfer_size); // pad with 0xff
128 if(fread(file_buf, size, 1, f) != 1)
129 {
130 perror("read error");
131 fclose(f);
132 return 1;
133 }
134 fclose(f);
135
136 uint8_t *xfer_buf = malloc(1 + xfer_size);
137 uint8_t *p = xfer_buf;
138
139 *p++ = 0x01; /* Report id */
140
141 /* Command block wrapper */
142 *p++ = 'B'; /* Signature */
143 *p++ = 'L';
144 *p++ = 'T';
145 *p++ = 'C';
146 put32le(p, 0x1); /* Tag */
147 p += 4;
148 put32le(p, size); /* Payload size */
149 p += 4;
150 *p++ = 0; /* Flags (host to device) */
151 p += 2; /* Reserved */
152
153 /* Command descriptor block */
154 *p++ = 0x02; /* Firmware download */
155 put32be(p, size); /* Download size */
156
157 ret = libusb_control_transfer(dev,
158 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 0x9, 0x201, 0,
159 xfer_buf, xfer_size + 1, 1000);
160 if(ret < 0)
161 {
162 printf("transfer error at init step\n");
163 return 1;
164 }
165
166 for(i = 0; i < nr_xfers; i++)
167 {
168 xfer_buf[0] = 0x2;
169 memcpy(&xfer_buf[1], &file_buf[i * xfer_size], xfer_size);
170
171 ret = libusb_control_transfer(dev,
172 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
173 0x9, 0x202, 0, xfer_buf, xfer_size + 1, 1000);
174 if(ret < 0)
175 {
176 printf("transfer error at send step %d\n", i);
177 return 1;
178 }
179 }
180
181 ret = libusb_interrupt_transfer(dev, 0x81, xfer_buf, xfer_size, &recv_size,
182 1000);
183 if(ret < 0)
184 {
185 printf("transfer error at final stage\n");
186 return 1;
187 }
188
189 printf("ret %i\n", ret);
190
191 return 0;
192}
193
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c
new file mode 100644
index 0000000000..c1d1e9aa34
--- /dev/null
+++ b/utils/imxtools/sbtools/sbtoelf.c
@@ -0,0 +1,303 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Bertrik Sikken
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
22/*
23 * .sb file parser and chunk extractor
24 *
25 * Based on amsinfo, which is
26 * Copyright © 2008 Rafaël Carré <rafael.carre@gmail.com>
27 */
28
29#define _ISOC99_SOURCE /* snprintf() */
30#include <stdio.h>
31#include <errno.h>
32#include <stdlib.h>
33#include <string.h>
34#include <ctype.h>
35#include <time.h>
36#include <stdarg.h>
37#include <strings.h>
38#include <getopt.h>
39
40#include "crypto.h"
41#include "elf.h"
42#include "sb.h"
43#include "misc.h"
44
45/* all blocks are sized as a multiple of 0x1ff */
46#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
47
48/* If you find a firmware that breaks the known format ^^ */
49#define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0)
50
51#define crypto_cbc(...) \
52 do { int ret = crypto_cbc(__VA_ARGS__); \
53 if(ret != CRYPTO_ERROR_SUCCESS) \
54 bug("crypto_cbc error: %d\n", ret); \
55 }while(0)
56
57/* globals */
58
59char *g_out_prefix;
60
61static void elf_printf(void *user, bool error, const char *fmt, ...)
62{
63 if(!g_debug && !error)
64 return;
65 (void) user;
66 va_list args;
67 va_start(args, fmt);
68 vprintf(fmt, args);
69 va_end(args);
70}
71
72static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
73{
74 FILE *f = user;
75 fseek(f, addr, SEEK_SET);
76 fwrite(buf, count, 1, f);
77}
78
79static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id)
80{
81 char name[5];
82 char *filename = xmalloc(strlen(g_out_prefix) + 32);
83 sb_fill_section_name(name, id);
84 sprintf(filename, "%s%s.%d.elf", g_out_prefix, name, count);
85 if(g_debug)
86 printf("Write boot section %s to %s\n", name, filename);
87
88 FILE *fd = fopen(filename, "wb");
89 free(filename);
90
91 if(fd == NULL)
92 return ;
93 elf_write_file(elf, elf_write, elf_printf, fd);
94 fclose(fd);
95}
96
97static void extract_sb_section(struct sb_section_t *sec)
98{
99 if(sec->is_data)
100 {
101 char sec_name[5];
102 char *filename = xmalloc(strlen(g_out_prefix) + 32);
103 sb_fill_section_name(sec_name, sec->identifier);
104 sprintf(filename, "%s%s.bin", g_out_prefix, sec_name);
105 FILE *fd = fopen(filename, "wb");
106 if(fd == NULL)
107 bugp("Cannot open %s for writing\n", filename);
108 if(g_debug)
109 printf("Write data section %s to %s\n", sec_name, filename);
110 free(filename);
111
112 for(int j = 0; j < sec->nr_insts; j++)
113 {
114 assert(sec->insts[j].inst == SB_INST_DATA);
115 fwrite(sec->insts[j].data, sec->insts[j].size, 1, fd);
116 }
117 fclose(fd);
118 }
119
120 int elf_count = 0;
121 struct elf_params_t elf;
122 elf_init(&elf);
123
124 for(int i = 0; i < sec->nr_insts; i++)
125 {
126 struct sb_inst_t *inst = &sec->insts[i];
127 switch(inst->inst)
128 {
129 case SB_INST_LOAD:
130 elf_add_load_section(&elf, inst->addr, inst->size, inst->data);
131 break;
132 case SB_INST_FILL:
133 elf_add_fill_section(&elf, inst->addr, inst->size, inst->pattern);
134 break;
135 case SB_INST_CALL:
136 case SB_INST_JUMP:
137 elf_set_start_addr(&elf, inst->addr);
138 extract_elf_section(&elf, elf_count++, sec->identifier);
139 elf_release(&elf);
140 elf_init(&elf);
141 break;
142 default:
143 /* ignore mode and nop */
144 break;
145 }
146 }
147
148 if(!elf_is_empty(&elf))
149 extract_elf_section(&elf, elf_count, sec->identifier);
150 elf_release(&elf);
151}
152
153static void extract_sb_file(struct sb_file_t *file)
154{
155 for(int i = 0; i < file->nr_sections; i++)
156 extract_sb_section(&file->sections[i]);
157}
158
159static void usage(void)
160{
161 printf("Usage: sbtoelf [options] sb-file\n");
162 printf("Options:\n");
163 printf(" -?/--help\tDisplay this message\n");
164 printf(" -o <prefix>\tEnable output and set prefix\n");
165 printf(" -d/--debug\tEnable debug output*\n");
166 printf(" -k <file>\tAdd key file\n");
167 printf(" -z\t\tAdd zero key\n");
168 printf(" -r\t\tUse raw command mode\n");
169 printf(" -a/--add-key <key>\tAdd single key (hex or usbotp)\n");
170 printf(" -n/--no-color\tDisable output colors\n");
171 printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n");
172 printf("Options marked with a * are for debug purpose only\n");
173 exit(1);
174}
175
176static void sb_printf(void *user, bool error, color_t c, const char *fmt, ...)
177{
178 (void) user;
179 (void) error;
180 va_list args;
181 va_start(args, fmt);
182 color(c);
183 vprintf(fmt, args);
184 va_end(args);
185}
186
187static struct crypto_key_t g_zero_key =
188{
189 .method = CRYPTO_KEY,
190 .u.key = {0}
191};
192
193int main(int argc, char **argv)
194{
195 bool raw_mode = false;
196 const char *loopback = NULL;
197
198 while(1)
199 {
200 static struct option long_options[] =
201 {
202 {"help", no_argument, 0, '?'},
203 {"debug", no_argument, 0, 'd'},
204 {"add-key", required_argument, 0, 'a'},
205 {"no-color", no_argument, 0, 'n'},
206 {"loopback", required_argument, 0, 'l'},
207 {0, 0, 0, 0}
208 };
209
210 int c = getopt_long(argc, argv, "?do:k:zra:nl:", long_options, NULL);
211 if(c == -1)
212 break;
213 switch(c)
214 {
215 case -1:
216 break;
217 case 'l':
218 if(loopback)
219 bug("Only one loopback file can be specified !\n");
220 loopback = optarg;
221 break;
222 case 'n':
223 enable_color(false);
224 break;
225 case 'd':
226 g_debug = true;
227 break;
228 case '?':
229 usage();
230 break;
231 case 'o':
232 g_out_prefix = optarg;
233 break;
234 case 'k':
235 {
236 if(!add_keys_from_file(optarg))
237 bug("Cannot add keys from %s\n", optarg);
238 break;
239 }
240 case 'z':
241 {
242 add_keys(&g_zero_key, 1);
243 break;
244 }
245 case 'r':
246 raw_mode = true;
247 break;
248 case 'a':
249 {
250 struct crypto_key_t key;
251 char *s = optarg;
252 if(!parse_key(&s, &key))
253 bug("Invalid key specified as argument");
254 if(*s != 0)
255 bug("Trailing characters after key specified as argument");
256 add_keys(&key, 1);
257 break;
258 }
259 default:
260 abort();
261 }
262 }
263
264 if(argc - optind != 1)
265 {
266 usage();
267 return 1;
268 }
269
270 const char *sb_filename = argv[optind];
271
272 enum sb_error_t err;
273 struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err);
274 if(file == NULL)
275 {
276 color(OFF);
277 printf("SB read failed: %d\n", err);
278 return 1;
279 }
280
281 color(OFF);
282 if(g_out_prefix)
283 extract_sb_file(file);
284 if(g_debug)
285 {
286 color(GREY);
287 printf("[Debug output]\n");
288 sb_dump(file, NULL, sb_printf);
289 }
290 if(loopback)
291 {
292 /* sb_read_file will fill real key and IV but we don't want to override
293 * them when looping back otherwise the output will be inconsistent and
294 * garbage */
295 file->override_real_key = false;
296 file->override_crypto_iv = false;
297 sb_write_file(file, loopback);
298 }
299 sb_free(file);
300 clear_keys();
301
302 return 0;
303}
diff --git a/utils/imxtools/sbtools/sha1.c b/utils/imxtools/sbtools/sha1.c
new file mode 100644
index 0000000000..0ad05bb5cd
--- /dev/null
+++ b/utils/imxtools/sbtools/sha1.c
@@ -0,0 +1,150 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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/* Based on http://en.wikipedia.org/wiki/SHA-1 */
22#include "crypto.h"
23
24static uint32_t rot_left(uint32_t val, int rot)
25{
26 return (val << rot) | (val >> (32 - rot));
27}
28
29static inline void byte_swapxx(byte *ptr, int size)
30{
31 for(int i = 0; i < size / 2; i++)
32 {
33 byte c = ptr[i];
34 ptr[i] = ptr[size - i - 1];
35 ptr[size - i - 1] = c;
36 }
37}
38
39static void byte_swap32(uint32_t *v)
40{
41 byte_swapxx((byte *)v, 4);
42}
43
44void sha_1_init(struct sha_1_params_t *params)
45{
46 params->hash[0] = 0x67452301;
47 params->hash[1] = 0xEFCDAB89;
48 params->hash[2] = 0x98BADCFE;
49 params->hash[3] = 0x10325476;
50 params->hash[4] = 0xC3D2E1F0;
51 params->buffer_nr_bits = 0;
52}
53
54void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size)
55{
56 int buffer_nr_bytes = (params->buffer_nr_bits / 8) % 64;
57 params->buffer_nr_bits += 8 * size;
58 int pos = 0;
59 if(buffer_nr_bytes + size >= 64)
60 {
61 pos = 64 - buffer_nr_bytes;
62 memcpy((byte *)(params->w) + buffer_nr_bytes, buffer, 64 - buffer_nr_bytes);
63 sha_1_block(params, params->hash, (byte *)params->w);
64 for(; pos + 64 <= size; pos += 64)
65 sha_1_block(params, params->hash, buffer + pos);
66 buffer_nr_bytes = 0;
67 }
68 memcpy((byte *)(params->w) + buffer_nr_bytes, buffer + pos, size - pos);
69}
70
71void sha_1_finish(struct sha_1_params_t *params)
72{
73 /* length (in bits) in big endian BEFORE preprocessing */
74 byte length_big_endian[8];
75 memcpy(length_big_endian, &params->buffer_nr_bits, 8);
76 byte_swapxx(length_big_endian, 8);
77 /* append '1' and then '0's to the message to get 448 bit length for the last block */
78 byte b = 0x80;
79 sha_1_update(params, &b, 1);
80 b = 0;
81 while((params->buffer_nr_bits % 512) != 448)
82 sha_1_update(params, &b, 1);
83 /* append length */
84 sha_1_update(params, length_big_endian, 8);
85 /* go back to big endian */
86 for(int i = 0; i < 5; i++)
87 byte_swap32(&params->hash[i]);
88}
89
90void sha_1_output(struct sha_1_params_t *params, byte *out)
91{
92 memcpy(out, params->hash, 20);
93}
94
95void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data)
96{
97 uint32_t a, b, c, d, e;
98 a = cur_hash[0];
99 b = cur_hash[1];
100 c = cur_hash[2];
101 d = cur_hash[3];
102 e = cur_hash[4];
103
104 #define w params->w
105
106 memmove(w, data, 64);
107 for(int i = 0; i < 16; i++)
108 byte_swap32(&w[i]);
109
110 for(int i = 16; i <= 79; i++)
111 w[i] = rot_left(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
112
113 for(int i = 0; i<= 79; i++)
114 {
115 uint32_t f, k;
116 if(i <= 19)
117 {
118 f = (b & c) | ((~b) & d);
119 k = 0x5A827999;
120 }
121 else if(i <= 39)
122 {
123 f = b ^ c ^ d;
124 k = 0x6ED9EBA1;
125 }
126 else if(i <= 59)
127 {
128 f = (b & c) | (b & d) | (c & d);
129 k = 0x8F1BBCDC;
130 }
131 else
132 {
133 f = b ^ c ^ d;
134 k = 0xCA62C1D6;
135 }
136 uint32_t temp = rot_left(a, 5) + f + e + k + w[i];
137 e = d;
138 d = c;
139 c = rot_left(b, 30);
140 b = a;
141 a = temp;
142 }
143 #undef w
144
145 cur_hash[0] += a;
146 cur_hash[1] += b;
147 cur_hash[2] += c;
148 cur_hash[3] += d;
149 cur_hash[4] += e;
150}