Nokia N95 – broken display and OVI won’t connect…

posted by on 2015.06.21, under general
21:

Suddenly the display of an old Nokia N95 stopped working. On power on the phone vibrated – but nothing more. Sliding the display up and down created some scratchy sounds – a good indication for a broken foil flex cable. According to Murphy’s law this only happens if you haven’t done any backup and you need some of the contacts stored on the phone urgently…

In this situation (according to some reports I found in the net) you try to connect the phone to a (Windows)PC running the Nokia OVI suite – and if you haven’t changed anything related to the phones way on how to connect to a PC – you can press the okay-button on the phone, OVI will detect it and you can sync the data to the PC. But this didn’t work for me – of course :-(.

As it was really urgent to get some of the contacts I decided to fix the display by repairing the broken flex cable. After opening the phone I found two of them – back-on-back – connecting the phone body with the (sliding) display. And happily the one with only 5 traces was broken. I used a scalpel to scratch down to the copper of each side of each trace, applied some flux and soldered some small pieces of (solid) wire on top of the flex cable.

fixed_cable

This is definitively the ugliest thing I ever did. But after a half hour of scratching and soldering the display came back to live.

running

The OVI suite uses sqlite as storage backend. To be able to push the contacts (and messages) from the backup to another platform I wrote two small scripts for reading the sqlite-DB’s and writing the data to stdout (formated using XML).

ESP8266 GPIO output performance

posted by on 2015.05.14, under programming, collected, electronics
14:

While building an extreme feedback device utilizing the ESP8266 and a bunch of WS2812B LEDs I missed some detailed information about the GPIO output performance of the ESP8266. This was a more general demand – but I ended up with my own WS2812 driver. And it was fun to use NOPs to achieve a nearly perfect timing (… cause I still remember the good old days when we used NOPs to create awesome rasterbars on the C64).

setup / basics

The XTENSA lx106 runs at 80 Mhz and has interrupts and watchdog disabled during measurement (see below).
Excerp from https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers – I/O addresses used to control the GPIO hardware:

0x60000304 - set GPIO pin HIGH
0x60000308 - set GPIO pin LOW
0x60000310 - set GPIO pin direction output
0x60000314 - set GPIO pin direction input

Xtensa calling convention

*** this part is just here for completeness ***

The lx106 used in the ESP8266 implements the CALL0 ABI offering a 16-entry register file (see Diamond Standard 106Micro Controller brochure). By this we can apply the calling convention outlined in the Xtensa ISA reference manual, chapter 8.1.2 CALL0 Register Usage and Stack Layout:

a0 - return address
a1 - stack pointer
a2..a7 - arguments (foo(int16 a,long long b) -> a2 = a, a4/5 = b), if sizefof(args) > 6 words -> use stack
a8 - static chain (for nested functions: contains the ptr to the stack frame of the caller)
a12..a15 - callee saved (registers containing values that must be preserved for the caller)
a15 - optional stack frame ptr

Return values are placed in AR2..AR5. If the offered space (four words) does not meet the required amount of memory to return the result, the stack is used.

disabling interrupts

According to the Xtensa ISA (Instruction Set Architecture) manual the Xtensa processor cores supporting up to 15 interrupt levels – but the used lx106 core only supports two of them (level 1 and 2). The current interrupt level is stored in CINTLEVEL (4 bit, part of the PS register, see page 88). Only interrupts at levels above CINTLEVEL are enabled.

In esp_iot_sdk_v1.0.0/include/osapi.h the macros os_intr_lock() and os_intr_unlock() are defined to use the ets_intr_lock() and ets_intr_unlock() functions offered by the ROM. The disassembly reveals nothing special:

disassembly – ets_intr_lock() and ets_intr_unlock():

ets_intr_lock():
40000f74:  006320      rsil  a2, 3           // a2 = old level, set CINTLEVEL to 3 -> disable all interrupt levels supported by the lx106
40000f77:  fffe31      l32r  a3, 0x40000f70  // a3 = *mem(0x40000f70) = 0x3fffcc0
40000f7a:  0329        s32i.n  a2, a3, 0       // mem(a3) = a2 -> mem(0x3fffdcc0) = old level -> saved for what?
40000f7c:  f00d        ret.n

ets_intr_unlock():
40000f80:  006020      rsil  a2, 0           //enable all interrupt levels
40000f83:  f00d        ret.n

To avoid the overhead of the function call and the unneeded store operation the following macros to enable / disable interrupts can be used:

macros for disabling/enabling interrupts:

#define XT_CLI __asm__("rsil a2, 3");
#define XT_STI __asm__("rsil a2, 0");

NOTE: the ability to run rsil from user code without triggering a PriviledgedInstruction exception implies that all code is run on ring0. This matches the information given here https://github.com/esp8266/esp8266-wiki/wiki/Boot-Process

the watchdog

Just keep it disabled. I run into a lot of trouble with it – seemed the wdt_feed() didn’t work for me.
…and its not (well) documented at all.

Some pieces of information I found in the net:

gpio_output_set(uint32 set_mask, uint32 clear_mask, uint32 enable_mask, uint32 disable_mask)

declared in: esp_iot_sdk_v1.0.0/include/gpio.h
defined in: ROM (eagle.rom.addr.v6.ld -> PROVIDE ( gpio_output_set = 0x40004cd0 ))

C example:

gpio_output_set(BIT2, 0, BIT2, 0);  // HIGH
gpio_output_set(0, BIT2, BIT2, 0);  // LOW
gpio_output_set(BIT2, 0, BIT2, 0);  // HIGH
gpio_output_set(0, BIT2, BIT2, 0);  // LOW

disassembly – call to gpio_output_set(BIT2, 0, BIT2, 0):

40243247:       420c            movi.n  a2, 4                                     // a2 = 4
40243249:       030c            movi.n  a3, 0                                     // a3 = 0
4024324b:       024d            mov.n   a4, a2                                    // a4 = 4
4024324d:       205330          or      a5, a3, a3                                // a5 = 0
40243250:       f79001          l32r    a0, 40241090 <system_relative_time+0x18>  // a0 = *mem(40241090) = 0x40004cd0
40243253:       0000c0          callx0  a0                                        // call 0x40004cd0 - gpio_output_set

disassembly – gpio_output_set (thanks to By0ff for the ROM dump):

> xtensa-lx106-elf-objdump -m xtensa -EL  -b binary --adjust-vma=0x40000000 --start-address=0x40004cd0 --stop-address=0x40004ced -D 0x4000000-0x4011000/0x4000000-0x4011000.bin

0x4000000-0x4011000/0x4000000-0x4011000.bin:     file format binary

Disassembly of the .data section:

40004cd0 <.data+0x4cd0>:
40004cd0:       f0bd61          l32r    a6, 0x40000fc4  // a6 = *mem(0x40000fc4) = 0x60000200
40004cd3:       0020c0          memw                    // finish all mem operations before next op
40004cd6:       416622          s32i    a2, a6, 0x104   // mem(a6 + 0x104) = a2 -> mem(0x60000304) = 4 (SET)
40004cd9:       0020c0          memw
40004cdc:       426632          s32i    a3, a6, 0x108   // mem(a6 + 0x108) = a3 -> mem(0x60000308) = 0 (CLR)
40004cdf:       0020c0          memw
40004ce2:       446642          s32i    a4, a6, 0x110   // mem(a6 + 0x110) = a4 -> mem(0x60000310) = 4 (DIR -> OUTPUT)
40004ce5:       0020c0          memw
40004ce8:       456652          s32i    a5, a6, 0x114   // mem(a6 + 0x114) = a5 -> mem(0x60000314) = 0 (DIR -> INPUT)
40004ceb:       f00d            ret.n                   // return to the caller

> od -A x -j 0xfc4 -N 4 -x 0x4000000-0x4011000/0x4000000-0x4011000.bin
000fc4 0200 6000            // *mem(0x40000fc4) = 0x60000200
000fc8

gpio_output_set()

gpio_output_set()

The whole cycle of a HIGH-RISE/LOW/HIGH-RISE transition takes 1160 nano seconds – the execution of one call to gpio_output_set() takes ~580ns (~46 cycles@80Mhz). Since the clear operation is executed after the set operation (see the code above) the LOW period is slightly shorter then the HIGH period (HIGH: 675ns, LOW: 485ns). By setting an initial LOW GPIO to HIGH and LOW in the same command a short pulse of 88 nano seconds length (~7 cycles) is created.

The macro GPIO_OUTPUT_SET(gpio_no, bit_value) – defined in esp_iot_sdk_v1.0.0/include/gpio.h – is just a wrapper for gpio_output_set():

#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
    gpio_output_set(bit_value<<gpio_no, ((~bit_value)&0x01)<<gpio_no, 1<<gpio_no,0)

WRITE_PERI_REG(addr, val)

Macro defined in esp_iot_sdk_v1.0.0/include/eagle_soc.h:

#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val)

It boils down to the following assembly instructions:

4024323a:       080000          excw
4024323d:       600003          excw                // --> *mem(4024323c) -> 0x60000308

40243240:       000304          excw
40243243:       f03d60          subx8   a3, a13, a6 // --> *mem(40243240) -> 0x60000304

// set
40243252:       fffb21          l32r    a2, 40243240 <eagle_lwip_getif+0x28>    // a2 = 0x60000304
40243255:       230c            movi.n  a3, 4                                   // a3 = 4
40243257:       0020c0          memw
4024325a:       0239            s32i.n  a3, a2, 0                               // mem(a2 + 0) = a3 -> mem(0x60000308) = 4

// clear
4024325c:       fff821          l32r    a2, 4024323c <eagle_lwip_getif+0x24>    // a2 = 0x60000308
4024325f:       430c            movi.n  a3, 4                                   // a3 = 4
40243261:       0020c0          memw
40243264:       0239            s32i.n  a3, a2, 0                               // mem(a2 + 0) = a3 -> mem(0x60000308) = 4   

To avoid optimization by the compiler I used the following hand crafted code for the measurement:

...
__asm__("movi    a2, 0x60000304  \n" // will be converted to literal load - l32r    a2, 40243240 <eagle_lwip_getif+0x28>
    "movi.n  a3, 4       \n"
    "memw           \n"
    "s32i.n  a3, a2, 0     \n"
    );

__asm__("movi    a2, 0x60000308  \n"
    "movi.n  a3, 4       \n"
    "memw           \n"
    "s32i.n  a3, a2, 0     \n"
    );
...

The disassembly shows that the movi is converted to a literal load (as expected):

...
40243248:       fffd21          l32r    a2, 4024323c <eagle_lwip_getif+0x24>
4024324b:       430c            movi.n  a3, 4
4024324d:       0020c0          memw
40243250:       0239            s32i.n  a3, a2, 0
40243252:       fffb21          l32r    a2, 40243240 <eagle_lwip_getif+0x28>
40243255:       430c            movi.n  a3, 4
40243257:       0020c0          memw
4024325a:       0239            s32i.n  a3, a2, 0
...

write_peri_reg()

write_peri_reg()

The whole cyle of a HIGH-RISE/LOW/HIGH-RISE transition takes 237ns nano seconds with a HIGH-period
of 100 ns (8 cycles) and a LOW-period of 137 ns (11 cycles – the HIGH-period is three cycles shorter
then the LOW period – maybe caused by one additional instruction fetch).

By avoiding the mov and removing the memw operations I was able to generate pulses with a period time of 150ns (12 cycles, HIGH: ~52ns, LOW: ~98ns).


__asm__("movi    a2, 0x60000304  \n"
    "movi    a4, 0x60000308  \n" 
    "movi.n  a3, 4       \n"  // GPIO2
    "memw           \n"
    "s32i.n  a3, a2, 0     \n"
    "s32i.n  a3, a4, 0     \n"
    "s32i.n  a3, a2, 0     \n"
    "s32i.n  a3, a4, 0     \n"
    "s32i.n  a3, a2, 0     \n"
    "s32i.n  a3, a4, 0     \n"
  );

fastest - T: ~150ns

fastest – T: ~150ns

WS2812B timing

…this was the starting point that forced me to have a deeper look into that topic. There are already some implementations for controlling the WS2812B. They work – just use them. This part is for fun and education … ahh, lets do it in plain assembly.

static inline void WS2812B_SEND_1(int port) 
{
  //800ns HIGH & 450ns LOW
  __asm__ volatile ("movi    a2, 0x60000304  \n"
            "movi    a3, 0x60000308  \n"
            "movi    a4, %0      \n"
            "s32i    a4, a2, 0     \n"
            "memw            \n"
            "movi    a5, 14         \n"
            "3:            \n"
            "addi    a5, a5, -1    \n"
            "bnez    a5, 3b      \n"
            "nop.n           \n"
            "nop.n           \n"
            "nop.n           \n"
            "nop.n           \n"
            "nop.n           \n"
            "s32i    a4, a3, 0     \n"
            "memw            \n"
            "movi    a5, 2         \n"
            "4:            \n"
            "addi    a5, a5, -1    \n"
            "bnez    a5, 4b      \n"
           :: "g" (port)
           : "a2", "a3", "a4", "a5"
           );
}

ws2812b - send logical 1

ws2812b – send logical 1

SEND_1_HIGH: 796ns
SEND_1_LOW:  454ns

static inline void WS2812B_SEND_0(int port) 
{
  //400ns HIGH & 850ns LOW
  __asm__ volatile ("movi    a2, 0x60000304  \n"
            "movi    a3, 0x60000308  \n"
            "movi    a4, %0      \n"
            "s32i    a4, a2, 0     \n"
            "memw            \n"
            "movi    a5, 7         \n"
            "1:            \n"
            "addi    a5, a5, -1    \n"
            "bnez    a5, 1b      \n"
            "nop.n           \n"
            "s32i    a4, a3, 0     \n"
            "memw            \n"
            "movi    a5, 10         \n"
            "2:            \n"
            "addi    a5, a5, -1    \n"
            "bnez    a5, 2b      \n"
            "nop.n           \n"
            "nop.n           \n"
              "nop.n           \n"
           :: "g" (port)
           : "a2", "a3", "a4", "a5"
           );
}

ws2812b - send logical 0

ws2812b – send logical 0

SEND_0_HIGH: 397ns
SEND_0_LOW: 855ns

experiences

  1. Add a ~400 ohm resistor into the WS2812 data input line to avoid oscillation caused by reflections of the input of the first LED.

    write_peri_reg() - no resistor

    write_peri_reg() – no resistor

  2. Use decoupling capacitors – without I got strange noise on the power supply line.

    pwr supply - noise bursts

    pwr supply – noise bursts


    pwr supply - single bursts

    pwr supply – single bursts

  3. Ensure the WS2812 data line uses a proper signal level. According to the data sheet DATA_IN is treated as HIGH above 3.5V (0.7*Vdd) and LOW below 1.5V (0.3*Vdd)). The Vhigh of 3.3V offered by the ESP9266 is not enough for the WS2812B to be detected as a clean HIGH signal (I got some strange flickers – after adding a 4050 as level shifter everything was fine).
  4. Disable interrupts during bit-banging the WS2812. Avoid disabled interrupts for more then 10ms or wireless connections will act wired. Keeping that in mind you will be able to write ~300 LEDs at once (1250ns per bit, 8 bit per color, 3 colors = 30us, internal overhead when switching to the next pixel = 225ns, keep 50us between each write for reset condition). If you need to run the code from above from flash check the timing using an oscilloscope. I have seen NOPs taking more then one cycle…
  5. Wear sunscreen.

Useful links

MS SQL generated XML – cleanup and sanitize

posted by on 2015.02.22, under sql
22:

All recent versions of MS SQL are able to generate the XML representation of a SQL query result on the fly:

>select * from dbo.foo
id  foo
1  dead
2  beef

>select * from dbo.foo for XML RAW, ELEMENTS

<row>
  <id>1</id>
  <foo>dead</foo>
</row>
<row>
  <id>2</id>
  <foo>beef</foo>
</row>

This is nothing new and special (in the age of NO-SQL and document centric databases) and works well. If you go to use the SQL server as a data source in a business integration orchestration the XML representation of the SQL results turns the mapping of the data between different entities into a point and click game…

While playing with the example databases of Microsoft NAV I recognised some funny things.

UTF-16 conversion of column names

Some smart guy decided to use spaces and braces within the column names. To turn these column names into valid XML element names Microsoft decided to convert these characters into their UTF-16 representation surrounded by underscores. By applying this rule a column named ‚Ali Baba‘ will turn into ‚Ali_x0020_Baba‘. It turned out that the conversation is applied to nearly every special character used within column names:

<test.dbo.foo xmlns:colon="uri">
  <space_x0020_sign>1</space_x0020_sign>
  <exclamation_x0021_sign>1</exclamation_x0021_sign>
  <doublequote_x0022_sign>1</doublequote_x0022_sign>
  <hash_x0023_sign>1</hash_x0023_sign>
  <dollar_x0024_sign>1</dollar_x0024_sign>
  <percent_x0025_sign>1</percent_x0025_sign>
  <amp_x0026_sign>1</amp_x0026_sign>
  <singlequote_x0027_sign>1</singlequote_x0027_sign>
  <openparentheses_x0028_sign>1</openparentheses_x0028_sign>
  <closingparentheses_x0029_sign>1</closingparentheses_x0029_sign>
  <mul_x002A_sign>1</mul_x002A_sign>
  <plus_x002B_sign>1</plus_x002B_sign>
  <comma_x002C_sign>1</comma_x002C_sign>
  <minus-sign>1</minus-sign>
  <dot.sign>1</dot.sign>
  <slash_x002F_sign>1</slash_x002F_sign>
  <colon:sign>1</colon:sign>
  <semicolon_x003B_sign>1</semicolon_x003B_sign>
  <lesserthen_x003C_sign>1</lesserthen_x003C_sign>
  <equal_x003D_sign>1</equal_x003D_sign>
  <biggerthe_x003E_sign>1</biggerthe_x003E_sign>
  <questionmark_x003F_sign>1</questionmark_x003F_sign>
  <at_x0040_sign>1</at_x0040_sign>
  <backslash_x005C_sign>1</backslash_x005C_sign>
  <caret_x005E_sign>1</caret_x005E_sign>
  <underscore_sign>1</underscore_sign>
  <pipe_x007C_sign>1</pipe_x007C_sign>
  <opencurly_x007B_sign>1</opencurly_x007B_sign>
  <closingcurly_x007D_sign>1</closingcurly_x007D_sign>
  <tilde_x007E_sign>1</tilde_x007E_sign>
</test.dbo.foo>

This is a minor problem cause it just creates ugly element names. If the data is only exported (and no ‚translation‘ back in the database is needed), these encoded entities can be replaced with anything looking … better – like the underscore. This is just for cosmetic purposes – nothing a machine will take a notice of…

IF OBJECT_ID (N'dbo.cleanXMLElements', N'FN') IS NOT NULL
    DROP FUNCTION dbo.cleanXMLElements
GO

-- replace any occurence of _x00<VALUE@REPLACE>_ with the string given by the second argument
-- warning: this is a pure pattern matching - if the sequence _x00<VALUE@REPLACE>_ is part of your payload - good luck!
-- note: to increase performance - remove any values from @REPLACE not needed
-- param_0: xml document
-- param_1: replacement string
-- return: cleaned xml document
CREATE FUNCTION dbo.cleanXMLElements (@XMLDoc XML, @REPLACE_WIDTH VARCHAR(10))
RETURNS xml
AS
BEGIN
  DECLARE @XMLString NVARCHAR(MAX)
  DECLARE @REPLACE VARCHAR(100)
  -- hex-values of elements that should be replaced, match is done on _x00<value>_
  SET @REPLACE = '20,21,22,23,24,25,26,27,28,29,2a,2b,2c,2f,3b,3c,3d,3e,3f,40,5c,5e,7c,7b,7d,7e'
  SET @XMLString = CAST(@XMLDoc as NVARCHAR(MAX))

  WHILE LEN(@REPLACE) > 0
  BEGIN
    SET @XMLString = REPLACE(@XMLString, '_x00' + LEFT(@REPLACE, CHARINDEX(',', @REPLACE + ',')-1) + '_', @REPLACE_WIDTH)
    SET @REPLACE = STUFF(@REPLACE, 1, CHARINDEX(',', @REPLACE + ','), '')
  END
  RETURN CAST(@XMLString as XML)
END
GO

XML name spaces

If a column name contains a colon the XML export will fail:

>SELECT * FROM dbo.foo for XML AUTO, ELEMENTS, TYPE

Msg 6846, Level 16, State 1, Line 4
XML name space prefix 'colon' declaration is missing for FOR XML column name 'colon:sign'.

In XML the construct A:B defines B as an element living in the name space of A (here: sign is part of the name space colon). Since the generated XML representation lacks the needed name space definition so the document is not well formed…

Unhappily it is very likely that the colon is part of the values contained in the query/document so the simple approach to just replace/strip all colons is very error prone. It is also not possible to generate the name space definition on the fly (eg. by parsing the table definition). The only remaining solution for that kind of problem is to add the needed name space definition manually:

WITH XMLNAMESPACES ('uri' as colon)
SELECT * FROM dbo.foo for XML AUTO, ELEMENTS, TYPE

This eliminates the option to export large databases automatically – if there is a colon in a column name. Of course its still possible to generate the needed code…

invalid characters in XML document

Back to the NAV example database… I tried to insert the rows of the Item table as XML into another table (trigger based logging) – and the command failed caused by some illegal characters contained into the values of some fields (example):

USE test
GO

IF OBJECT_ID (N'dbo.log', N'U') IS NOT NULL
    DROP TABLE dbo.log
GO

CREATE TABLE dbo.log (
  id int IDENTITY(1,1),
  tab_name VARCHAR(20),
  data XML
);
GO
insert into dbo.log values('Item', (SELECT * FROM [Demo Database NAV (8-0)].[dbo].[CRONUS AG$Item] for xml raw, elements, BINARY BASE64))

Msg 9420, Level 16, State 1, Line 10
XML parsing: line 1, character 5458, illegal xml character

I dumped the XML and found &#x04 at the position given in the error message. The ASCII code 0x04 represents the special character EOT – End Of Transmission (I have no idea how the guy that created the example table was able to put that special char into the table data). Since 0x04 is not allowed in XML documents the conversion fails. Maybe I’m to demanding – but why the hell is the freaking tool that converts the SQL result to its XML representation not able to handle/filter that kind of special char? Hu? Have a look at http://www.w3.org/TR/xml/#charsets to get an idea what is allowed – and what not.

To workaround this misbehaviour just remove these illegal characters from the XML document before any further processing. Since the generated XML is not valid it is not possible to handover the converted SQL result directly to the sanitizer function so an explicit cast to nvarchar is needed here.

USE test
GO

IF OBJECT_ID (N'dbo.sanitizeXML', N'FN') IS NOT NULL
    DROP FUNCTION dbo.sanitizeXML
GO

-- remove any occurrence of &#x<VALUE@REMOVE>;
-- warning: this is a pure pattern matching - if the sequence &#x<VALUE@REMOVE> is part of your payload - good luck!
-- note: to increase performance - remove any values from @REMOVE not needed
-- param_0: text to be sanitized
-- return: sanitized string
--CREATE FUNCTION dbo.sanitizeXML (@XMLDoc XML)
CREATE FUNCTION dbo.sanitizeXML (@XMLString NVARCHAR(max))
RETURNS XML
AS
BEGIN
  --DECLARE @XMLString NVARCHAR(MAX)
  DECLARE @REMOVE VARCHAR(100)
  -- hex-values of elements that should be removed, match is done on &#x<value>;
  -- 0x05 -> ENQ
  -- 0x04 -> EOT
  -- full set: 00,01,02,03,04,05,06,07,08,0b,0c,0e,0f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f
  SET @REMOVE = '04,05'

  WHILE LEN(@REMOVE) > 0
  BEGIN
    SET @XMLString = REPLACE(@XMLString, '&#x' + LEFT(@REMOVE, CHARINDEX(',', @REMOVE + ',') - 1) + ';', '')
    SET @REMOVE = STUFF(@REMOVE, 1, CHARINDEX(',', @REMOVE + ','), '')
  END
  RETURN CAST(@XMLString as XML)
END
GO

insert into dbo.log (tab_name, data) values('Item', (select test.dbo.sanitizeXML(CAST((SELECT * FROM [Demo Database NAV (8-0)].[dbo].[CRONUS AG$Item] for xml raw, elements, BINARY BASE64) AS NVARCHAR(MAX)))))

For performance reasons the sanitizeXML currently only handles the special chars I have to deal with. In theory every char from 0x00 up to 0x1f (except 0x09, 0x0a, 0x0d) must be removed.

Scripts and examples: sanitize_and_cleanup_xml_sql.zip

OpenWrt Barrier Breaker metarouter instance on MikroTik RB-2011

posted by on 2015.01.10, under general, configuration, networking, collected
10:

THE PATCH PUBLISHED IN THIS ARTICLE IS NOT COMPLETE. AT LEAST THE VIRTUAL MACHINE WILL CRASH SPORADICALLY UPON RECEIVING NETWORK PACKETS USING THE VIRTUAL INTERFACES. I WIIL TRY TO FIX THIS ASAP.

While looking around for a new router for my home network I stumbled over the RB2011UiAS-2HnD-IN produced by MikroTik. It uses a AR9344-DC3A-R SOC (@600Mhz) and offers a broad range of interfaces:

  • 5x 1Gbit copper ports (+ 1x SFP copper/fiber)
  • 5x 100 MBit copper ports
  • 128 MB of RAM and FLASH
  • 802.11 b/g/n wireless interface
  • a micro USB 2.0 port (that can be used to attach storage using an OTG cable)
  • a small color touch display
  • a CISCO-style RJ45 console port

All that is covered by a solid metal chassis and sold for ~120 € – not that bad.The LINUX-based routerOS offers an intuitive CLI – but there is no way to install private packages. So I had a look at openwrt.org to check if OpenWrt is running on this thingy… – it does. But after digging a little bit deeper I found something really awesome: it is possible to run up to 7 virtual instances of OpenWrt on top of the router OS using a mechanism called Metarouter. And each of the instances can be connected to the environment (the external network / other instances, …) using

  • the physical network ports of the router and
  • virtual interfaces connected to other virtual/physical interfaces using (LINUX-) bridges.

That creates the ability to reduce the footprint of my hardware infrastructure significantly by using (buzzword mode on) consolidation via virtualization (buzzword mode off). In fact, by using Metarouter(s) I’m able to replace two „fat“ routers (one running a public access point [currently a WRT 54G], another on used inside our home network [a TPLINK WR1043ND]) and a smaller one (TPLINK 703N) running my private JABBER server by one box. And the concept of having bridges connecting virtual and physical interfaces makes the whole setup a way easier to handle (splitting the network into a private and public network using just one WRT54G + OpenWrt was no fun). And at the end of the day I can keep all my configurations used in the old OpenWrt based setup…

The sad thing: MikroTik only provided support (by publishing patches) for OpenWrt up to Backfire (10.3, first release in 4/2010, 2.6.31) – and I was not able to find any sign that they will continue. Happily liquidcz from the MikroTik forum was able to create a patch usable for Attitude Adjustment (12.09, 4/2013, kernel 3.3). This worked fine – but the successor of AA – Barrier Breaker (10/2014, kernel 3.10.49) brought lots of updates (mainly related to the packages – but also to the kernel). I picket up liquidcz patch and adapted it to be usable with Barrier Breaker. And it was easier then expected :). So this is the outline on how to build OpenWrt Barrier Breaker to be used as a virtual instance on a MikroTik router:

build the firmware image for Mikrotik metarouter

wget http://openwrt.naberius.de/barrier_breaker/mr-mips/openwrt_metarouter_1407.patch
git clone git://git.openwrt.org/14.07/openwrt.git barrier_breaker
cd barrier_breaker
patch -p1 &amp;lt; ../openwrt_metarouter_1407.patch
make defconfig
make prereq
make menuconfig
# select &#039;Mikrotik MetaROUTER MIPS&#039; as target system; save and exit, build...
make -j $(nproc)

The created image is placed in bin/mr-mips/.

build additional packages

./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig
# select the packages you need and run make again...
make -j $(nproc)

You can find the packages in bin/mr-mips/packages/.

build all packages

# the option CONFIG_ALL=y (build all packages) didn&#039;t work for me
# I removed all packages and re-installed them using the flag -d m - default for newly installed packages
./scripts/feeds remove -a
./scripts/feeds install -a -d m
make -j $(nproc)

trouble shooting

  • if a build using make -j $(nproc) fails, rerun with make -j1
  • if it still fails, rerun with make -j1 V=s
  • if the builder is not able to fetch a packet, check if you could find another source and adapt the Makefile located in the packages// director

Since the flash storage of the router is accessible via FTP, the created image can be pushed down to the device using curl…

curl -T openwrt-mr-mips-rootfs.tar.gz ftp://192.168.1.120 --user admin:

Creating a virtual instance on the router is done using CLI metarouter command:
[admin@MikroTik] &amp;gt; metarouter import-image file-name=openwrt-mr-mips-rootfs.tar.gz
imported: 100%

looking up /rw/vm/8
[admin@MikroTik] &amp;gt; metarouter print
Flags: X - disabled
#   NAME MEMORY-SIZE   DISK-SIZE       USED-DISK STATE
0   mr8  16MiB         unlimited       6711kiB   running

[admin@MikroTik] &amp;gt; metarouter console mr8
...
BusyBox v1.22.1 (2015-01-10 00:19:59 CET) built-in shell (ash)
Enter &#039;help&#039; for a list of built-in commands.

_______                     ________        __
|       |.-----.-----.-----.|  |  |  |.----.|  |_
|   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
|_______||   __|_____|__|__||________||__|  |____|
|__| W I R E L E S S   F R E E D O M
-----------------------------------------------------
BARRIER BREAKER (Barrier Breaker, r43889)
-----------------------------------------------------
* 1/2 oz Galliano         Pour all ingredients into
* 4 oz cold Coffee        an irish coffee mug filled
* 1 1/2 oz Dark Rum       with crushed ice. Stir.
* 2 tsp. Creme de Cacao
-----------------------------------------------------
root@OpenWrt:/# free
total         used         free       shared      ...
Mem:         13480        10468         3012
-/+ buffers:              10468         3012

As you could see, BB is very demanding in the context of memory (even a stripped BB firmware – more or less all services from the default image removed, no IPv6 support – needs at least 9 MB). Since the stock router offers ~110 MB of free RAM you can easily run up to 4 instances where each uses 24 MB.

The setup of network interfaces is well documented in the metarouter manual and straight forward.

If you need to store a lot of data you can use the micro USB port to attach any USB storage using an OTG-cable:

[admin@MikroTik] &amp;gt; store disk print
Flags: S - system
#   NAME TOTAL-SPACE    FREE-SPACE STATUS
0 S system 126976KiB      43440KiB ready
1   usb1    985192KiB     967532KiB ready

IMPORTANT: The USB drive must be formated with the (proprietary) MetaFS filesystem – so all data on the USB drive is lost.

Since the storage of the router is exported via FTP, curlftpfs can be used to mount a folder located on the attached USB drive into the local file system of an OpenWrt instance. Do not try to abuse the system as NAS device – the storage access eats the CPU (if you do a file transfer to the USB storage the CPU usage goes up to 100%).

ressources / links

original patch created by liquidcz: here

patch for Barrier Breaker: openwrt_metarouter_1407.patch

default fw image (Barrier Breaker, r43889): openwrt-mr-mips-default-image-rootfs.tar.gz

lowered memory footprint: openwrt-mr-mips-small-image-rootfs.tar.gz

image builder: OpenWrt-ImageBuilder-mr-mips-for-linux-x86_64.tar.bz2

binary packages: here

 

Have phun!

collected: shiny new update keys for 1.2.4

posted by on 2013.10.24, under general, linux, collected
24:

some background on how the update works

On startup the shine checks the external sdcard for some special files. If there is a file named update.zip, the system starts with /dev/block/mmcblk0p4 mounted as filesystem root – and /sbin/recovery is executed.

You can find the code that forms that little binary here.
_note: in the head section of recovery.cpp you can find a short outline on how update „notification“ works

First recovery checks the cryptographic signature of the update.zip by

  1.  reading the public keys (yes, plural is possible – see load_keys in verifier.cpp) from /res/keys (stored in the recovery partition),
  2.  creating the hash over the update.zip,
  3.  extracting the signature embedded in the comment section,
  4.  decrypt hash by using the public keys from /res/keys and
  5.  compare own hash with hash from the signature.

After a successful verification of the update.zip the zip-container itself is opened and recovery checks for /META-INF/com/google/android/update-binary and – if it is present – executes it. The binary then starts running the script stored in /META-INF/com/google/android/updater-script that performs the installation steps. The script itself is written in edify – see here for a short overview.

_note: for hunting bugs during the update process cat /tmp/recovery.log

replace the key – old version / pre 1.2.4

Currently only the public key used by the Telekom is stored in the /res/keys-file. So only the owner of the private key – the Telekom – can create valid update-files (by signing them).

By replacing the public key in the shine by using the well-known testing key contained in the android sources everyone can create valid update files (and of course – you can re-sign the public update from the Telekom to use them too – if you want).

_note: you can find the keys here

First you must convert the key to the format the recovery expects. This is done by using the tool dumpkey – you can find the source here.


java -jar dumpkey.jar testkey.x509.pem &gt; testkey.x509.c

gives you

{64,0xc926ad21,{1795090719,2141396315,950055447,-1713398866,-26044131,1920809988,546586521,-795969498,1776797858,-554906482,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,-1731647369,323993566,28517732,609753416,1826472888,215237850,-33324596,-245884705,-1066504894,774857746,154822455,-1797768399,-1536767878,-1275951968,-1500189652,87251430,-1760039318,120774784,571297800,-599067824,-1815042109,-483341846,-893134306,-1900097649,-1027721089,950095497,555058928,414729973,1136544882,-1250377212,465547824,-236820568,-1563171242,1689838846,-404210357,1048029507,895090649,247140249,178744550,-747082073,-1129788053,109881576,-350362881,1044303212,-522594267,-1309816990,-557446364,-695002876},{-857949815,-510492167,-1494742324,-1208744608,251333580,2131931323,512774938,325948880,-1637480859,2102694287,-474399070,792812816,1026422502,2053275343,-1494078096,-1181380486,165549746,-21447327,-229719404,1902789247,772932719,-353118870,-642223187,216871947,-1130566647,1942378755,-298201445,1055777370,964047799,629391717,-2062222979,-384408304,191868569,-1536083459,-612150544,-1297252564,-1592438046,-724266841,-518093464,-370899750,-739277751,-1536141862,1323144535,61311905,1997411085,376844204,213777604,-217643712,9135381,1625809335,-1490225159,-1342673351,1117190829,-57654514,1825108855,-1281819325,1111251351,-1726129724,1684324211,-1773988491,367251975,810756730,-1941182952,1175080310}}

If your shine is already rooted, use your ADB shell and do the following:


# cd /mnt/sdcard
# mkdir mnt_recovery
# mount -t ext2 /dev/block/mmcblk0p4 mnt_recovery
# busybox cp mnt_recovery/res/keys mnt_recovery/res/keys.bck
# cat &lt;&lt; 'EOF' &gt; mnt_recovery/res/keys
{64,0xc926ad21,{1795090719,2141396315,950055447,-1713398866,-26044131,1920809988,546586521,-795969498,1776797858,-554906482,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,-1731647369,323993566,28517732,609753416,1826472888,215237850,-33324596,-245884705,-1066504894,774857746,154822455,-1797768399,-1536767878,-1275951968,-1500189652,87251430,-1760039318,120774784,571297800,-599067824,-1815042109,-483341846,-893134306,-1900097649,-1027721089,950095497,555058928,414729973,1136544882,-1250377212,465547824,-236820568,-1563171242,1689838846,-404210357,1048029507,895090649,247140249,178744550,-747082073,-1129788053,109881576,-350362881,1044303212,-522594267,-1309816990,-557446364,-695002876},{-857949815,-510492167,-1494742324,-1208744608,251333580,2131931323,512774938,325948880,-1637480859,2102694287,-474399070,792812816,1026422502,2053275343,-1494078096,-1181380486,165549746,-21447327,-229719404,1902789247,772932719,-353118870,-642223187,216871947,-1130566647,1942378755,-298201445,1055777370,964047799,629391717,-2062222979,-384408304,191868569,-1536083459,-612150544,-1297252564,-1592438046,-724266841,-518093464,-370899750,-739277751,-1536141862,1323144535,61311905,1997411085,376844204,213777604,-217643712,9135381,1625809335,-1490225159,-1342673351,1117190829,-57654514,1825108855,-1281819325,1111251351,-1726129724,1684324211,-1773988491,367251975,810756730,-1941182952,1175080310}}
EOF
# sync

Of course – you can also add the testkey to the key already contained in the key file. Just run step 5 in the following color:


cat &lt;&lt; 'EOF' &gt;&gt; mnt_recovery/res/keys
, {64,0xc926ad21,{1795090719,2141396315,950055447,-1713398866,-26044131,1920809988,546586521,-795969498,1776797858,-554906482,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,-1731647369,323993566,28517732,609753416,1826472888,215237850,-33324596,-245884705,-1066504894,774857746,154822455,-1797768399,-1536767878,-1275951968,-1500189652,87251430,-1760039318,120774784,571297800,-599067824,-1815042109,-483341846,-893134306,-1900097649,-1027721089,950095497,555058928,414729973,1136544882,-1250377212,465547824,-236820568,-1563171242,1689838846,-404210357,1048029507,895090649,247140249,178744550,-747082073,-1129788053,109881576,-350362881,1044303212,-522594267,-1309816990,-557446364,-695002876},{-857949815,-510492167,-1494742324,-1208744608,251333580,2131931323,512774938,325948880,-1637480859,2102694287,-474399070,792812816,1026422502,2053275343,-1494078096,-1181380486,165549746,-21447327,-229719404,1902789247,772932719,-353118870,-642223187,216871947,-1130566647,1942378755,-298201445,1055777370,964047799,629391717,-2062222979,-384408304,191868569,-1536083459,-612150544,-1297252564,-1592438046,-724266841,-518093464,-370899750,-739277751,-1536141862,1323144535,61311905,1997411085,376844204,213777604,-217643712,9135381,1625809335,-1490225159,-1342673351,1117190829,-57654514,1825108855,-1281819325,1111251351,-1726129724,1684324211,-1773988491,367251975,810756730,-1941182952,1175080310}}
EOF

Note the comma surrounded by TWO spaces (SPACEKOMMASPACE) in front of the key (and the >> instead of > to append data). If you keep the Telekom key inside of the key-file you can install Telekom update-files without doing anything (but that contains the risk that the big magenta just kicks out the testkey – and locks the device finally).

_note: if you accidentally whipped out the Telekom key (as I did) – here is a backup:


{64,0x43e8c79d,{3676113227,1369749849,185223027,4193363093,2748936052,3982115949,2510941709,3179856730,3334762442,877424379,1572534478,379110109,3828184589,896326794,3259452337,1537333391,1527246812,1948881733,2695224641,3229564848,935338986,1880890185,1109044213,3584680280,2980215301,1048464167,1625211812,3380609409,1325015002,3048088550,3309007604,856748852,2742900622,1536007600,534693848,362616682,1757112249,1124497581,2589504072,3233109600,1483976042,1367799680,3874016522,3186374915,314458865,2533711827,917955710,2798363551,1533164771,21896696,577058097,4118697084,2950684889,1199785220,896256126,2013061576,3648332184,512726633,3829734369,3492448310,1658713944,2502792484,2381120692,2638223166},{2804200884,415193597,2952297320,1796440253,3760790861,2358398962,1319099071,1797194474,3920925071,3251309220,3091529551,3449146706,501734315,1726066195,2560662010,922451496,3625301210,3511962485,3446896765,2852859028,3995066542,3771896184,1498517695,1518271224,2813835315,2438495713,4214917633,1229593951,2879391816,2953200436,49762796,702148507,896186987,2106390057,3257996684,2916017064,2570034595,545791097,3544317144,1467421123,2340085279,3793830820,1463904638,2299616657,16368580,1993463273,20991070,1752616193,1008234173,2481181795,2499980873,904917164,906206298,2700276043,1728187988,1246428162,2078812943,732584325,881425958,3846779747,1384713822,2197399727,1513320059,731791506}}

If your shine is not rooted yet (and the serial number is below 20311241 – and you have not installed the update 1.2.4) you can just download the recovery.img.fixed_initrd_and_testkey, put it on a sdcard (!!!DO NOT FORGET TO RENAME IT TO recovery.img!!!) and restart your shine. On boot the shine starts to install the image in the background – so just wait (do nothing) till the reader goes down. Power it on again and your shine has ADB access and the testkey installed.

To sign an update.zip just run


java -jar signapk.jar -w testkey.x509.pem testkey.pk8 update.zip update_signed.zip

Then copy the update_signed.zip to your sdcard (and rename it to update.zip).

Example: update zip that just replaces the startup logo of the shine…

Intermezzo: The startup logo

The system/bin/upgrade.sh tells us that the logo lives in /dev/block/mmcblk0@18432 (bs=512). The name suggest that the image uses a 4 bit raw format – native resolution of the display is 1024×758 (makes 388096 bytes).

To prove that, I did a quick


dd if=/dev/block/mmcblk0 bs=1 skip=9437184 count=388096 of=raw_logo

Moved the file to my desktop and fired


cat raw_logo.org | convert -depth 4 -size 1024x758+0 gray:- pic.png

on it. Result:

Tolino Shine startup logo

Tolino Shine startup logo

_note: convert is part of imagemagic

After changing the image recreate the 4-bit-grayscale image with


convert logo_rework.png -size 1024x758+0 -depth 4 logo_rework.gray

Now write the raw image back to the shine using dd again:

dd if=logo_rework.gray of=/dev/block/mmcblk0 bs=1 seek=9437184

Reboot and enjoy your new startup logo!

back to the update example…

It just contains a short example of the META-INF/com/google/android/updater-script that invokes a one-liner shell script – nothing more.


ui_print("!!! this is only a demo !!!");
show_progress(0.05, 2);
assert(getprop("ro.product.device") == "imx50_rdp" || getprop("ro.build.product") == "imx50_rdp");
ui_print("Target device check: ok");
ui_print("use it for something usefull...");
show_progress(0.45, 90);
package_extract_file("install_logo.sh", "/tmp/install_logo.sh");
package_extract_file("logo.raw", "/tmp/logo.raw");
set_perm(0, 0, 0755, "/tmp/install_logo.sh");
set_perm(0, 0, 0555, "/tmp/logo.raw");
run_program("/tmp/install_logo.sh");

_note: never forget the empty newline at the end of the edify scripts!
_note: never forget to set proper permissions for your shell scripts!!
_note: never forget to add the bash bang on top of your shell scripts!!!

important_note: after installing 1.2.4 the shine reports itself as imx50_rdp_2 – so the above example must be adapted!!!

This update can be used to check if the testkey is installed.

the 1.2.4 update

I used the ability to sign my own update-packages to rework the latest update for the old shine. A rough overview of what I have done:

  • add android testkey to all /res/keys
  • add ADB on startup (hardcoded in upgrade_check.sh, /system/bin/adb)
  • add su (/system/bin/su)
  • fixes wrong waveform-target in upgrade_check.sh
  • adds user_script.sh-hook in upgrade_check.sh
  • re-enables recovery.img-hook in upgrade_check.sh
  • add links to some tools (no need to write busybox in front of every important command)
  • enable ADB in recovery
  • added imx50_rdp_2 in the target test of the updater-script („big update“ can be installed over and over)

I used the update downloaded from Hugendubel. See the repack_and_sign.sh script in the downloads to get an idea on how it is done (trust me – its easy). To proceed for your own, just

  1. unpack the update.zip
  2. unpack the orig_update inside the update to orig_update
  3. replace META-INF/com/google/android/updater-script in update and orig_update by the ones used in the provided reworked
  4. replace all /res/keys-files to add testkey
  5. change the default.prop (secure = 0; debug=1, adb = 1)
  6. replace all upgrade_check.sh by provided one
  7. run pack_and_sign.sh…

_note: Watch the asserts inside of the updater-script. If they catch in the updater may tell misleading error messages. Just add verbose debug! And as noted above: have an eye to cat /tmp/recovery.log…

_note: tested by starting on a shine with 1.0.1 (rooted), installed recovery that brings the testkeys, than loaded the reworked 1.2.4 update…

the dead end – waveform.bin

Together with frank-w from the lesen.net-forum we discussed an upgrade-way over the waveform cause it is also written by upgrade_check.sh – without any checks:


...
elif [ -e /mnt/sdcard/extsd/waveform.bin ]; then
echo "---&gt; Programming waveform ----------------------------------------"
busybox dd if=/mnt/sdcard/extsd/waveform.bin of=/dev/mmcblk0 bs=512 seek=14336
sync
...

Since the waveform binary is located in front of /mmcblk0p1 („MEIN TOLINO“) and – even more important – /mmcblk0p2 aka /system we had the idea to overwrite these two partitions by offering a waveform image that contains these parts. It sounded promising and worked on the console (directly on the shine – just dd the waveform + partition image). But on startup – the upgrade_check catches in and starts writing – the shine goes mad and killed all processes cause he runs out of memory… strange. But then, ohhhhh, that hurts so much: the actual device on the shine lives in /dev/block/mmcblk0 – but the upgrade_check writes to /dev/mmcblk0. And that is mounted via tmpfs. So on start – while writing to the NEW file /dev/mmcblk0 dd eats all the memory. Nice bug. Or was that intentional, Mr. big magenta? Huh?

left overs…

The process of changing the keys / building updates etc was not really straight forward. It took some hours of testing… here are some snippets that turned out to be useful…

If you wanna change the /system – remount rw:


mount -o remount,rw /dev/block/mmcblk0p2 /system

The su binary needs the set u-id permissions:


chmod 6555 /system/bin/su

Script that adds the testkeys in /mmcblk0p4/res/keys (recovery partition):


#!/system/bin/bash
mkdir /mnt/sdcard/recovery
mount -t ext2 /dev/block/mmcblk0p4 /mnt/sdcard/recovery
cp /mnt/sdcard/recovery/res/keys /mnt/sdcard/recovery/res/keys.org
echo " , {64,0xc926ad21,{1795090719,2141396315,950055447,-1713398866,-26044131,1920809988,546586521,-795969498,1776797858,-554906482,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,-1731647369,323993566,28517732,609753416,1826472888,215237850,-33324596,-245884705,-1066504894,774857746,154822455,-1797768399,-1536767878,-1275951968,-1500189652,87251430,-1760039318,120774784,571297800,-599067824,-1815042109,-483341846,-893134306,-1900097649,-1027721089,950095497,555058928,414729973,1136544882,-1250377212,465547824,-236820568,-1563171242,1689838846,-404210357,1048029507,895090649,247140249,178744550,-747082073,-1129788053,109881576,-350362881,1044303212,-522594267,-1309816990,-557446364,-695002876},{-857949815,-510492167,-1494742324,-1208744608,251333580,2131931323,512774938,325948880,-1637480859,2102694287,-474399070,792812816,1026422502,2053275343,-1494078096,-1181380486,165549746,-21447327,-229719404,1902789247,772932719,-353118870,-642223187,216871947,-1130566647,1942378755,-298201445,1055777370,964047799,629391717,-2062222979,-384408304,191868569,-1536083459,-612150544,-1297252564,-1592438046,-724266841,-518093464,-370899750,-739277751,-1536141862,1323144535,61311905,1997411085,376844204,213777604,-217643712,9135381,1625809335,-1490225159,-1342673351,1117190829,-57654514,1825108855,-1281819325,1111251351,-1726129724,1684324211,-1773988491,367251975,810756730,-1941182952,1175080310}}" &gt;&gt;/mnt/sdcard/recovery/res/keys
sync
umount /mnt/sdcard/recovery/

Just put it on your external sd card, name it user_script.sh. If everything was okay, you will find the script (after restarting the shine) renamed to user_script.sh.success. If anything went wrong and the script does not return 0 the file becomes user_script.sh.failure.

If you miss some links to busybox tools:


nice_to_have="touch chgrp cp diff find vi nc pidof grep tar zip unzip wget du sed watch more arp seq sleep usleep tail head wc"; for tool in $nice_to_have ; do ln /system/bin/busybox /system/bin/$tool ; done

 

downloads

file content size/mb md5
part_one.zip
  • dumpkey.jar – output public key as c-source (used in res/keys)
  • keys.telekom_and_testkey – /res/keys-file containing original and testkey
  • mkkey.sh – old script from the Android repos to generate own keys
  • recovery.img.fixed_initrd_and_testkey – Tolino recovery.img containing adb, root – and the testkey (but only the testkey – so you can install the reworked 1.2.4 update)
  • signapk.jar – tool to sign apks / zips
  • testkey.pk8 , testkey.x509.pem – the Android testkeys
  • su, adbd – tolino binaries from old versions
  • update_example_change_startlogo_signed_testkey.zip – update that was signed with the testkey, replaces the startlogo of the shine
  • upgrade_check.sh – reworked upgrade_check
  • updater-script – adds links for important tools, set su permissions, allows rdp and rdp_2
  • blink.sh – just fade the backlight (to signal something is currently running)
  • repack_and_sign.sh – automate packing and signing for 1.2.4
72 13362ef4bf5c73c9f9cfd0bd4f1628ce
update_hugendubel_1_2_4_reworked_testkey.zip
  • 1.2.4 update from hugendubel
  • ADB + root
  • original and testkey
  • user_script install hook
  • re-enabled recovery.img in upgrade_check
136 b80ed49bdb04685975bae414ade5d538
shine_housing.zip detailed pictures of the plastic enclosure of the shine (in case you have to open it – note the noses around the border of the back part, the top cover is also glued to the display frame and the housing of the connectors at the bottom with double sided tape – lift it carefully and slowly. maybe some warm air from a hairdryer removes some adhesive power. but be careful to not overheat the display – stay cool at all) 0.7 31f8869f0de1c1ee3b3f629a1698dc69

Have phun!

free your packets

posted by on 2013.09.15, under general, security
15:

I was about to write a technical article on how to use an OpenVPN tunnel (provided by Cyberghost) over a wireless access point running OpenWRT – just for myself and some paranoid reasons (thank you Diego for a mental disease). But then Mr. Snowdn started to publish documents… so I decided to offer my neighborhood access to the Internet in a free, anonymous and restriction-less way by setting up an open wireless access point that uses a tunnel with endpoint in Sweden.

If you would like to setup your own you can find a HowTo on freepackets.org.

collected: shiny ADB and root – the f*c**@! (:=easy) way

posted by on 2013.06.26, under linux, collected, security
26:

I AM SO STUPID. I was looking for a way to exploit that little thingy by using some buffer overflow or some other coding mumbo jumbo… the hard way. And there is a script that writes the whole recovery image on the shine without any checks… the f*c**@! way. Telekom, sometimes I love you for your lack of… …and it gives us an open Tolino Shine WITHOUT the need of opening the device. Gotcha!

These are the lines I’m talking about (system/bin/upgrade_check.sh):


elif [ -e /mnt/sdcard/extsd/recovery.img ] || [ -e /cache/upgrade/recovery.img ]; then
    echo "---> Programming partition RECOVERY ----------------------------------"
    busybox dd if=/mnt/sdcard/extsd/recovery.img of=/dev/block/mmcblk0p4 bs=8M
    busybox dd if=/cache/upgrade/recovery.img of=/dev/block/mmcblk0p4 bs=8M
    sync
    sync
    e2fsck -dy /dev/block/mmcblk0p4
    sync
    sync
    mv /mnt/sdcard/extsd/recovery.img /mnt/sdcard/extsd/recovery.img_old
    rm /cache/upgrade/recovery.img
    sync
    sync
    am start -a android.intent.action.ACTION_REQUEST_SHUTDOWN

Yes. If there is a file recovery.img on your external SD card it is written to the shine. Without any check. Be careful! If you broke something the next step is to open your device to recover the SD image. If you boot the shine in recovery mode, mmcblk0p4 becomes the root-fs…


Kernel command line: console=ttymxc0 ... init=/init root=/dev/mmcblk0p4 ...

ADB (+root) is locked by init.rc and default.prop – inside of the initrd. So we must rewrite that part of the SD card.

What to prepare:
1. rework the initrd (uramdisk.img in the update.zip) so ADB is enabled
2. put the new initrd inside of the recovery.img
3. change the init.rc in the recovery.img so it writes a initrd to the SD card

How it works:
1. put the changed recovery.img on a external SD card, plug it into the shine
2. boot the shine – the recovery image is updated silently (after that the shine goes down)
3. boot while holding POWER&HOME
4. wait for END of the script – reboot
5. the shine is free.

Lets extract some data to play with… in /system/bin/upgrade.sh you find these lines:


dump_ramdisk(){
....
busybox dd if=/cache/upgrade/uramdisk.img of=/dev/block/mmcblk0 bs=1M seek=6
                sync
                sync
....
}

The initrd is expected to take place at 0x600000 on the SD card – the loader header starts at 0x5ffff0, containing the well known magic number (FF 5F AF FF) and the size information (0x23701 = 145153 bytes, size=uboot-header+image-data=64+145089). The initrd itself is encapsulated in a u-boot-header (note the magic number 27 05 19 56 at the beginning).

Get the initrd out of the backup-image:


>dd if=backup_internal_sd_shine_after_sys_recover.img of=initrd.uboot.img bs=1 skip=6291456 count=145153
>export PATH=$PATH:/home/devel/projects/tolino_shine/own_uboot/uboot-imx/tools/
>devel@bigplay:~/projects/tolino_shine/backup_tolino_sd$ mkimage -l initrd.uboot.img 
Image Name:   ntxinitramfs
Created:      Tue Feb  5 06:38:45 2013
Image Type:   ARM Linux RAMDisk Image (uncompressed)
Data Size:    145089 Bytes = 141.69 kB = 0.14 MB
Load Address: 70308000
Entry Point:  70308000

Now we stript the u-boot header so we got the pure image file:


>dd if=initrd.uboot.img of=initrd.img bs=1 skip=64

The initrd.img is still compressed and packaged with cpio. To get the content of the ramdisk run


>mkdir initrd ; cd initrd
>zcat ../initrd.img | cpio -id
>ls
data          dev   init.freescale.rc  init.rc  sbin  system                ueventd.goldfish.rc
default.prop  init  init.goldfish.rc   proc     sys   ueventd.freescale.rc  ueventd.rc

Fire your favorite editor and change the following files:


****init.rc*****
service adbd /sbin/adbd
---      disabled
+++#     disabled
---------------------------
****default.prop****
---ro.secure=1
+++ro.secure=0
---ro.debuggable=0
+++ro.debuggable=1
---persist.service.adb.enable=0
+++persist.service.adb.enable=1

Repacking the initrd goes the other way around:


>find ./ | cpio -H newc -o > initrd.cpio.adb
>gzip initrd.cpio.adb
>mv initrd.cpio.adb.gz initrd.adb.img

_note: the new image is only 144858 bytes – 231 bytes smaller then the original.

Now add the u-boot header:


>mkimage -A arm -O linux -T ramdisk -C none -a 70308000 -e 70308000 -n "Tolino+ADB" -d initrd.adb.img initrd.adb.img.uboot
Image Name:   Tolino+ADB
Created:      Wed Jun 26 12:02:02 2013
Image Type:   ARM Linux RAMDisk Image (uncompressed)
Data Size:    144858 Bytes = 141.46 kB = 0.14 MB
Load Address: 70308000
Entry Point:  70308000

Half way done. Now lets write that new initrd to the SD card to check if ADB is enabled after boot…


#>dd if=initrd.adb.img.uboot of=/dev/SDCARD bs=512 seek=12288

_note: seek=12288*512=6291456=0x600000

After power on start ADB shell and be happy:


devel> adb devices
List of devices attached 
20030394  device
-
devel> adb shell
# id
uid=0(root) gid=0(root)
# 

The images:

md5 size/mb file
c57b4edd33c92bf2f52179166fcd289a 0.14 initrd.img.uboot.org
95c435c2339820eefe1bd06d81a5ddb0 0.14 initrd.adb.img.uboot

Yes, now we have ADB as root. But replacing the initrd this way that is only possible if you open the Shine… not good. But by the power of the recovery.img we will solve that problem. First get the partition that holds the recovery image. After having some trouble using kpartx and dd from the loops/mappings I decided to go the good old way…


#>sudo fdisk /dev/sdb
.....
Command (m for help): p
.....
   Device Boot      Start         End      Blocks   Id  System
.....
/dev/sdb4         7185411     7709699      262144+  83  Linux
.....

_note: 7709699-7185411=524288 -> *512 (block size) = 268435456 bytes


>mkdir recovery; cd recovery
#>dd if=/dev/sdb of=recovery.img bs=512 count=524288 skip=7185411

Make a copy to keep the original file. If everything is okay we could mount it…


>mkdir recoverymnt
>cp recovery.img recovery.img.initrd
#>mount -o loop recovery.img.initrd recoverymnt
>cd recoverymnt

Now copy the initrd with enabled ADB into the recovery image and add a line in the init.rc script (before the line that contains service recovery /sbin/recovery):


#>cp ../../initrd/initrd.adb.img.uboot .
#>nano init.rc
---service recovery /sbin/recovery
+++service adbroot replace_initrd.sh
+++   oneshot
+++
+++service recovery /sbin/recovery

_note: documentation of android init script syntax: readme.txt

Next step: add a little script that does the replacement job for us (and make it executable):


#>nano replace_initrd.sh
+++#!/system/bin/bash
+++if [ -e initrd.adb.img.uboot ] ; then
+++busybox echo "replace initrd with given image... this may take some seconds."
+++busybox dd if=initrd.adb.img.uboot of=/dev/block/mmcblk0 bs=512 seek=12288
+++busybox sync
+++busybox rm initrd.adb.img.uboot
+++busybox echo "initrd replaced. Reboot device and enjoy ADB+root!"
+++fi
#>chmod a+x replace_initrd.sh

Finally unmount the recovery-image and run a sanity check:


>cd ..
>sync
#>umount recoverymnt
>fsck.ext4 recovery.img.initrd 
e2fsck 1.42.5 (29-Jul-2012)
recovery: clean, 420/65536 files, 109353/262144 blocks

Now place the recovery.img.initrd on a micro SD card, plug the card inside the Tolino and boot.

_note: remember to rename the recovery.img.initrd to recovery.img and do a sync before pulling the card

The copy process for the recovery.img starts and runs in the background – do not try to do something useful with the device during the (hidden) copy process – it will hang. After the copy is done the scripts causes a shutdown. This basically means: plug the card into the shine, start it and wait till it is off again.
Now start the shine in recovery mode by pressing the HOME and POWER button together… and the magic happens as soon as init.rc is executed… wait till the shine asks you to restart or reset the device and reboot. Now ADB (as root) is enabled – persistent.

Here you can download the recovery images I used. Attention: use them on your own risk. I’m not responsible if you brick your device (but I can give you advices how to open it). If something is fuXXed up: I am not responsible! (Maybe someone else with an already opened shine should try that first, and again, and again…)

md5 size/mb file
43096205380ffe22f40aa251fdfcb34a 256 recovery.img.org
12b632ccda3d5ad0bee4b04606d6bf5b 256 recovery.img.initrd

Have fun!

collected: own shiny kernel on the tolino shine

posted by on 2013.06.23, under general, linux, programming, kernel, bootloader, collected
23:

The (patched) kernel used in the Tolino Shine was made available (by accident) a few weeks ago. I mirrored the archive here:

md5 size/mb file
90e78f2f7fdfffe460c85651cae431a3 109 kernel.tar.gz

Extract the archive, export the path to the toolchain (if not done yet) and compile the kernel:


>export PATH=$PATH:/home/devel/projects/tolino_shine/own_uboot/kobo/gcc-linaro-arm-linux-gnueabihf-4.8-2013.04-20130417_linux/bin/
>make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

U-boot uses a little header in front of images (kernel, initrd, …) to store informations about the content (so it knows how to handle the image data). Normally you could compile the kernel directly as u-boot compatible image by using the make target uImage – but lets do that by hand to see how it works (we need that u-boot header thingy again when it comes down to the initrd – so it is not about wasting time, won’t hurt and is done with one line… :) ).

_note: The mkimage tool is located in the tools folder of the u-boot sources so we need to export that path.


>export PATH=$PATH:/home/devel/projects/tolino_shine/own_uboot/uboot-imx/tools/
>mkimage -A arm -O linux -T kernel -C none -a 0x70008000 -e 0x70008000 -n "Shine Kernel" -d zImage shine_kernel.uboot
Image Name:   Shine Kernel
Created:      Sun Jun 23 16:13:38 2013
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    3275528 Bytes = 3198.76 kB = 3.12 MB
Load Address: 70008000
Entry Point:  70800000

_note: I took the address parameters -a (load address) and -e (execute address) from the original u-boot.

From ntx_comm.c (#define SD_OFFSET_SECS_KERNEL 2048) and the boot log (MMC read: dev # 0, block # 2048, count 8192 partition # 0 ) we know that the boot-loader expects the kernel at 0x800*0x200 = 0x100000 on the SD card.

_note: the #define DEFAULT_LOAD_KERNEL_SZ 8192 sets the maximum for the kernel size (here 4MB)

So lets write our u-boot header equipped kernel to that position on the disk…


#>dd if=shine_kernel.uboot of=/dev/SDCARD seek=2048 bs=512

It boots… and crashes:


MMC read: dev # 0, block # 1, count 1 partition # 0 ... 
1 blocks read: OK
hwcfg rootfstype : 2
hwcfg partition type : 7
## Booting kernel from Legacy Image at 70800000 ...
   Image Name:   Shine Kernel
   Created:      2013-06-23  16:05:55 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3275528 Bytes =  3.1 MB
   Load Address: 70008000
   Entry Point:  70008000
   Loading Kernel Image ... OK
OK
-
Starting kernel ...
-
Uncompressing Linux... done, booting the kernel.
Initializing cgroup subsys cpu
Linux version 2.6.35.3 (devel@bigplay) (gcc version 4.8.1 20130401 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.04-20130417 - Linaro GCC 2013.04) ) #109 PREEMPT Sun Jun 23 00:15:35 CEST 2013
CPU: ARMv7 Processor [412fc085] revision 5 (ARMv7), cr=10c53c7
..................
mxc_epdc_fb_fw_handler-3619] 
drivers/video/mxc/mxc_epdc_fb.c(3654):EPD 1024x758 
Unable to handle kernel NULL pointer dereference at virtual address 00000026
pgd = 80004000
[00000026] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT
last sysfs file: 
Modules linked in:
CPU: 0    Not tainted  (2.6.35.3 #109)
PC is at epdc_firmware_func+0x10c/0x2a4
LR is at epdc_firmware_func+0x68/0x2a4
................

The last regular output prints a file (drivers/video/mxc/mxc_epdc_fb.c) and a line number (3654). A few lines later (3694) some data is copied from waveform… remember the u-boot output @ boot:


...........
MMC read: dev # 0, block # 14335, count 1 partition # 0 ... 
1 blocks read: OK
no "waveform" bin header
...........

Yeah, it is missing- and the code will crash if it is not there. Learned: it seems the waveform contains the frame buffer configuration. Same procedure as every year: extract the waveform image from the SD card backup and put it on our new card… The header including the magic number starts at 0x6ffff0. The size is given at mem(magic number + 8) -> (AF 66 11 00). Interpreted as an unsigned long we got a size of 1140399 bytes (but we copy 1140431 := 1140399 + 32 byte header). The waveform data starts at 0x700000. Copy now!


>dd if=first_16_mb_sd_card.img of=waveform.img bs=1 skip=7340016 count=1140431
#>dd if=waveform.img of=/dev/SDCARD bs=1 seek=7340016 obs=512

md5 size/mb file
7d440e0d24b2ee89c280d83ecf55452d 1 waveform.img

Insert the card, cross the fingers – boot… works :). On boot the display is initialized – the screen turns black for two times. But now the kernel dies with:


VFS: Cannot open root device "mmcblk0p1" or unknown-block(179,1)
Please append a correct "root=" boot option; here are the available partitions:
b300         1966080 mmcblk0 driver: mmcblk
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,1)
[<8003d250>] (unwind_backtrace+0x0/0xe0) from [<8046c620>] (panic+0x68/0xd8)
[<8046c620>] (panic+0x68/0xd8) from [<80008e50>] (mount_block_root+0x1c0/0x200)
[<80008e50>] (mount_block_root+0x1c0/0x200) from [<800090c0>] (prepare_namespace+0x128/0x17c)
[<800090c0>] (prepare_namespace+0x128/0x17c) from [<80008aac>] (kernel_init+0x120/0x17c)
[<80008aac>] (kernel_init+0x120/0x17c) from [<80039954>] (kernel_thread_exit+0x0/0x8)

But that is okay and will be fixed in the next part. (Complete boot log including kernel: here)

collected: build u-boot for Tolino Shine

posted by on 2013.06.22, under linux, bootloader, collected
22:

I took the u-boot sources for imx507 from the official repo of the KOBO reader at git://github.com/kobolabs/Kobo-Reader.git cause I was unable to find a working u-boot repository that contains the mx50/imx507. Hey Deutsche Telekom, you should publish something… The u-boot source is located in Kobo-Reader/hw/imx507/u-boot-2009.08.tar.gz. To build the boot-loader you also need a matching tool-chain – happily you can find one also in the KOBO repo – this time in Kobo-Reader/toolchain/gcc-linaro-arm-linux-gnueabihf-4.8-2013.04-20130417_linux.tar.bz2. You could get both archives here (cause the full blown KOBO-Reader-Repo is currently about 3.5G – and you only need these two parts to start):

md5 size/mb file
244920ee3a01d3f8cd187d41ea06a718 14 u-boot-2009.08.tar.gz
998fb1f00b5f7eaea1cc2491960892fb 80 gcc-linaro-arm-linux-gnueabihf-4.8-2013.04-20130417_linux.tar.bz2

Copy both archives to a common directory and then:


>tar xzvf u-boot-2009.08.tar.gz
>tar xjvf gcc-linaro-arm-linux-gnueabihf-4.8-2013.04-20130417_linux.tar.bz2
>export PATH=$PATH:/home/devel/projects/tolino_shine/own_uboot/kobo/gcc-linaro-arm-linux-gnueabihf-4.8-2013.04-20130417_linux/bin/

_note 0: replace the exported path with yours!
_note 1a: if you use the files from the git repo – change the name of the used toolchain/gcc-prefix in u-boot-2009.08/build_mddr_256.sh and u-boot-2009.08/build.sh from arm-fsl-gnueabi- to arm-linux-gnueabihf-
_note 1b: The names are already changed in archives linked above.
_note2: For running the build_mddr_256.sh the program dialog (console based dialogs & menus) must be installed on your system.

Now you are ready to build:


>cd u-boot-2009.08/
>./u-boot-2009.08/build_mddr_256.sh

and choose E60610 board, K4X2G323PD – Go! The build process creates a file named u-boot_mddr_256-E60610-K4X2G323PD.bin (just the renamed u-boot.bin) – thats the boot-loader. Easy, huh?

Connect your SD card to your PC – use dmesg to make sure you take the right device for the next steps.
_warning: all data on the SD will be lost!
_note: tested it with 2GB – must not be a SDHC – old cards are working

The bootcode of the CPU expects the code at 0x400 on the SD card. The created image is already padded to fit this needs – so no seeking is needed – just write the image to the card:


#>dd if=u-boot_mddr_256-E60610-K4X2G323PD.bin of=/dev/SDCARD bs=512

The drawback of using the image with padding is, that if you write it to the SD card also the MBR is wiped out – means your partition table is also deleted. For development it is handy to just replace the u-boot and not the 0x400 bytes in front of it – so lets strip the image.


>dd if=u-boot_mddr_256-E60610-K4X2G323PD.bin of=u-boot_mddr_256-E60610-K4X2G323PD.bin.stripped bs=512 skip=2

Writing the stripped image is straight forward – and it keeps the MBR untouched/intact:


#>dd if=u-boot_mddr_256-E60610-K4X2G323PD.bin.stripped of=/dev/SDCARD bs=512 seek=2

_note: before starting developing you should clean the SD card entirely to be save from side-effects caused by old data:
#>dd if=/dev/zero of=/dev/SDCARD bs=512

Plug the card into the shine, connect serial adapter and power on… the first boot-up reveals some other stuff that is needed to boot the shine properly.


MMC read: dev # 0, block # 1023, count 1 partition # 0 ...
1 blocks read: OK
no "hwcfg" bin header
-
MMC read: dev # 0, block # 18431, count 1 partition # 0 ...
1 blocks read: OK
no "logo" bin header
-
MMC read: dev # 0, block # 14335, count 1 partition # 0 ...
1 blocks read: OK
no "waveform" bin header
boot normal : no hwconfig !
_init_tps65185_power(): cannot init without hwconfig !

At the moment I think the tps65185 is the most important – cause without the display powered up we will see nothing. The magic behind the hardware configuration is partly done in freescale/mx50_rdp/ntx_common.c. The array gszNtxBinMagicA contains the magic number (FF F5 AF FF) that is checked within the function _load_ntx_bin_header. The information about the size of the hardware configuration is the location of the magic number + 8 – so if we find the magic number in the image we could easily extract the hardware config of the shine to use it in our own build…

Looking at block 1023 (=0x7fe00) of the backup image for finding the magic number, according to the code…

Magic = 0x7fe00 + 0x200 – 0x10 -> 0x7FFF0 -> Gotcha!

BinSize = Magic + 8 -> 0x7FFF8 = 0x6e -> 110

…strange cause the size of the header is

+0x10 tagNTXHWCFG_HDR
+0x23 tagNTXHWCFG_VAL
———–
0x33

…and only that amount of memory is copied. Strange. But now we could extract the configuration from the backup image of the shine and put it on our SD card.


>dd if=first_16_mb_sd_card.img of=tolino_shine_hw_config.img skip=524272 bs=1 count=67
...
>hexdump -C tolino_shine_hw_config.img
00000000 ff f5 af ff 78 56 34 12 6e 00 00 00 00 00 00 00 |....xV4.n.......|
00000010 48 57 20 43 4f 4e 46 49 47 20 76 31 2e 36 00 26 |HW CONFIG v1.6.&amp;|
00000020 1e 0d 00 00 07 00 00 08 04 06 06 00 00 18 01 00 |................|
00000030 02 00 02 02 07 01 68 02 e4 00 00 02 02 02 00 01 |......h.........|
00000040 05 00 00 |...|
00000043

Now lets write the hardware configuration on the card and check what happens on boot.


#>dd if=tolino_shine_hw_config.img of=/dev/SDCARD seek=524272 bs=1

On boot now we get

....................
Kernel RAM visiable size=255M-&gt;255M
init TPS65185 power ...
....................

means the power control for the display is working now :)  You can find the complete boot log here.

_note: have a look at the source files in board/freescale/mx50_rdp – it is a great playground (eg. ntx_hwconfig.h explains what is stored inside the hw config blob)

Next step: adding a kernel and a initrd.

Useful to understand what the heck is done when compiling u-boot for a specific board: freescale IMX50 user guide

collected: exploring the tolino shine

posted by on 2013.06.19, under general, linux, kernel, bootloader, collected, security
19:

I played some days weeks with the Tolino Shine – an ebook reader offered by a consortium of different booksellers and developed by the Deutsche Telekom.
Two results: I’m confused about the idea behind Kafkas „Die Verwandlung“ and the reader is save – in the meaning of „lets enable ADB or gain root the easy way“.
More or less the girls/guys of the Telekom did a good job – only one little hole – but so far no major issue. I explored the shine in hard and software and this post is a sum-up of my findings regarding to this. On some points also some Android background knowledge pops up.

reading the file system

The Tolino Shine exports two drives over USB. One is linked to the internal flash (and named „Mein Tolino“ – with a space in the middle – idiots). The second drive appears only if an micro sd is inserted – as  an
unnamed device. I placed files with a fixed name on that drives and tried to access them via the browser by using an URL starting with file://sdcard/… and voilà, that worked well. Its a known issue for old browsers –
see CVE-2010-4804. This hole gives you access to all local files (if rights granted) and could be used to explore the Shine a little… it is possible to read parts of /proc – that gives you access to meminfo, cpuinfo and so on… a lot of useful informations – if you know nothing about a device. Some samples…


proc/partitions
major minor #blocks name
179 0 3872256 mmcblk0
179 1 2263552 mmcblk0p1
179 2 393216 mmcblk0p2
179 3 1 mmcblk0p3
179 4 262144 mmcblk0p4
179 5 524288 mmcblk0p5
179 6 393216 mmcblk0p6
179 8 1933312 mmcblk1
179 9 1933244 mmcblk1p1


/proc/cpuinfo
Processor : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 799.53
Features : swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc08
CPU revision : 5
Hardware : Freescale MX50 Reference Design Platform
Revision : 50011
Serial : 0000000000000000


/system/bin/upgrade_check.sh (cutted)
#!/system/bin/bash -x
i=0
rm /data/no_sd_upgrade
upgrade_check(){
sleep 6
if [ -e /mnt/sdcard/extsd/update.zip ] ; then
echo "---&gt; recovery mode setting ---------------------------------------"
rm /cache/downloadfile*
sync
sync
if [ -e /mnt/sdcard/extsd/update_mark ] ; then
# mv /mnt/sdcard/extsd/update.zip /mnt/sdcard/extsd/update.zip_old
rm /mnt/sdcard/extsd/update.zip
rm /mnt/sdcard/extsd/update_mark
upgrade_check
......
fi
elif [ -e /mnt/sdcard/extsd/waveform.bin ]; then
........
# xiaobo begin of adb_open
# elif [ -e /mnt/sdcard/extsd/adb_open ]; then
# setprop persist.service.adb.enable 1
# sync
# sync
# elif [ -e /mnt/sdcard/extsd/adb_close ]; then
# setprop persist.service.adb.enable 0
# sync
# sync
# xiaobo end of adb open
elif [ -e /mnt/sdcard/extsd/recovery.img ] || [ -e /cache/upgrade/recovery.img ]; then
echo "---&gt; Programming partition RECOVERY ----------------------------------"
......
am start -a android.intent.action.ACTION_REQUEST_SHUTDOWN
fi
}
upgrade_check

It is even possible to read binary files like the init or config.gz – that holds the config for building a kernel… a lot of files – a lot of typing – and it was really a pain to enter all that by hand. So I crafted a page that uses java script to read a local file, encode it into a JSON-string (big overhead – but that is encoding save in every way) and sends it to a server. The page contains a free form text field for entering file names directly, a list of known files (not all are working), and a word book attack that could be run in different locations (the word book was formed by creating permutations from a list single words and separators – not very clever… sorry). You need to place the .php-file on a server the Shine can access – and set
the upload password to something else then the given one – or some strange guys will use your server as some kind of drop box replacement. The upload is limited by the allowed POST-size of your server. Change the encoding of the transmitted data or add multipart file transfer if you like… here the sources, use on your own risk: readout Just copy shine.html and wl.js on the drive name „Mein Tolino“ and point the browser to file://sdcard/shine.html and you should get the following page:

read local files from the shine

read local files from the shine

Be creative… and report new files you have found on the device. Edit: don’t do it. Continue reading!

the update.zip

After getting a lot of informations from the device I tested its reaction on a file named update.zip by just ‚touching‘ it on the drives. After restarting the reader  he tried to install the update-file.
The file was empty – so a seek failed message was printed. A good sign that the shines update/recovery system uses the stock Android verifier code… In these days the long awaited update was made
available – but intercepting the update by sniffing the traffic turned out as ***nearly impossible*** – cause they use an SSL connection for transferring the update file. By sniffing the communication
I made two observations:

  1. wikipedia.de is called – I think this is the way they check …are we online?!?…
  2. a suspend-jpg is downloaded from http://www.pageplace.de/media/eink-reader/sleep_screen.jpg – no idea why (conspiracy theory: there is some hidden data in the image…)

But back to the update.zip… For security reasons normally an update-container is signed by the creator. That means that SHA1 was used on the data part to create an unique fingerprint and then the supplier uses a/his private (RSA) key to encrypt the hash. This encrypted hash is then placed as a comment (in a PKCS1.5 container) at the end of the update file (see verifier.cpp – gives an idea how comments are placed in zip files). On startup the device extracts the encrypted hash out of the update.zip, loads the public key (update.zip file res/keys contains an example) stored on the device, decrypts the encrypted hash and compares the result with a SHA1 hash created over the data part of the offered update.zip file… if both hashes are equal the update.zip is accepted. If not an „failed to verify whole-file signature“-error is printed and the device continues to boot. (btw: if you got a „signature is too short“ error the the update contains a comment – but not an PKCS1.5 container)

This information is very important cause most articles I found about repacking and signing update.zip files do not outline that the signature used for checking authenticity and validity  is based on a/some public key(s) stored on the device. To use self signed update files the recovery program must be replaced by a version that ignores the signature check or a new public key (for a known private key) must be installed on the device. Both ways are not open for now. So if you change something within the update file you are out of luck.

If you are going to create your own certificates for signing update-files, remember to use 3 as exponent for the RSA  (…at least for the Tolino – if I got it right e was changed back to 65537 in later Android versions).

According to the license pdf contained in the archive the Shine is updated to Android 2.3.4 – the license file contained in firmware 1.0.1 shows 2.3.3 as the used Android version.

shiny kernel

A nice guy (thank you, Hajo) shared a link to the kernel sources of the Tolino Shine. I think they were published by accident cause the download location is a formerly unprotected WordPress upload directory… The Shine uses a 2.6.35.3 Kernel – a diff against the sources from kernel.org returns the changes made for the Shine… mainly patches from freescale to support the MX-series, the Android parts and some additions made by the Shine firmware developers (Joseph? , Angela?, Daniel?) . You can compile and start it using qemu – but thats all – a booting kernel – nothing special.

at the end…

I was a little frustrated …I opened the shine – looking for a JTAG connector or at least a serial port. It was not that easy to open the cover cause the display frame is glued to the upper half of the enclosure using double sided tape… but after some sweating it was done. The entire board – the PCB and the display – is mounted to the bottom cover with 4 screws.

Tolino board mounted on backcover

Tolino board mounted on backcover

After removing them I was able to pull out the whole electronic body – nice.

borad_complete

The first thing that catches my attention was the micro SD located on the back of the board… wow, what a find. I did a backup of the whole card (after running the restore to factory process) – you can find the image here:

md5 size/mb file
9a9427be4988ac7050c77a9a023f0c1e 673 backup_internal_sd_shine_after_sys_recover.img.gz
0ec840258ec4b8161736fa55f1d45c09 16 first_16_mb_sd_card.img

Instead of using a dedicated NAND flash chip an SD card is used to store all persistent data… what the heck… that means: you can replace the complete system image without the hazel of a soldered NAND chip / JTAGing cause you can write the system to the SD an try it out… and there should be no way to brick the device cause you could replace the (persistent) memory  easily… and I was looking for a JTAG port… happiness. The partition table of the internal SD card as shown by parted and enriched with infos from recovery.fstab:


Number  Start   End     Size    Type      File system  Flags
1      15.7MB  2334MB  2318MB  primary   fat32                      /sdcard vfat /dev/block/mmcblk0p1   "Mein Tolino"
2      2334MB  2736MB  403MB   primary   ext4                       /system ext4 /dev/block/mmcblk0p2
3      2736MB  3679MB  943MB   extended
5      2737MB  3274MB  537MB   logical   ext4                       /data ext4 /dev/block/mmcblk0p5
6      3275MB  3678MB  403MB   logical   ext4                       /cache ext4 /dev/block/mmcblk0p6
4      3679MB  3947MB  268MB   primary   ext4                       recovery

There are 15 megs of space in front of the first partition – here my findings:


0x000000 - 0x0001bf filled with 0 - means: no boot loader
0x0001c0 - 0x0001ff partition table (ends with 55aa)
0x000200 - 0x00020a serial number (device type)
0x00020b            just a colon
0x00020c - 0x00022b another serial/a hash? (32 byte)
0x000400 - 0x02695f uboot (contains also the recovery)
0x07fff0 - 0x080035 HW Config v 1.6 - version string?
0x0e0002 - 0x0e07ff binary blubber
0x0f0002 - 0x0f07ff binary blubber
0x0ffff0 - 0x0fffff binary blubber
0x100000 - 0x10003f uboot header
0x100040 - 0x43122e kernel
0x5ffff0 - 0x6236ff initramfs
0x6ffff0 - 0x81658e binary blubber...

After browsing the endless hex-file and writing the fun down I found recovery:/system/bin/upgrade.sh – it shows a partly different partition scheme – but contains also useful informations.

shiny hardware

Here comes a list of the chips I found on the board:

plate function manufacturer data sheet/info
K4X2G323PD8GD8 DRAM 64Mx32 = 256 MB, 800 Mhz, 1.8V SAMSUNG
MCIMX507CVM8B Cortex A8, up to 800 Mhz Freescale www.freescale.com/webapp/sps/site/prod_summary.jsp?code=i.MX507
zForce NN1001 optical touch controller neonode & TI
TPS 65185 eInk power supply TI http://www.ti.com/product/tps65185
430G2333 micro controller (reading battery state?) TI http://www.ti.com/product/msp430g2333
430V325 micro controller (charging?) TI http://www.ti.com/product/msp430p325
wc121 single chip WLAN module cybertan http://www.cybertan.com.tw/products/WC121.html

cpu sdcard dram TPS65185 430G2333 m430v325 nn1001 wlan

serial reader

There are 3 serial ports on the board. The one next to the CPU (right side of the board) is … the serial port that is connected to the CPU. Using a proper interface with 3.3V signal level and a terminal program running at 115200 8N1 you can sniff the boot messages of u-boot and the kernel. Don’t forget to cross RX and TX and again: use 3.3V signal levels!

serial_connector_cpuserial_cpu

U-Boot 2009.08 ( 1月 25 2013 - 15:04:09)
-
CPU: Freescale i.MX50 family 1.1V at 800 MHz
mx50 pll1: 800MHz
mx50 pll2: 400MHz
mx50 pll3: 216MHz
ipg clock : 66666666Hz
ipg per clock : 66666666Hz
uart clock : 24000000Hz
ahb clock : 133333333Hz
axi_a clock : 400000000Hz
axi_b clock : 200000000Hz
weim_clock : 100000000Hz
ddr clock : 200000000Hz
esdhc1 clock : 80000000Hz
esdhc2 clock : 80000000Hz
esdhc3 clock : 80000000Hz
esdhc4 clock : 80000000Hz
Board: MX50 RDP board
Boot Reason: [POR]
Boot Device: SD
I2C: ready
DRAM: 256 MB
......................
MMC read: dev # 0, block # 14336, count 2228 partition # 0 ...
2228 blocks read: OK
Kernel RAM visiable size=254M-&gt;254M
Detecting HOME+POWER key for recovery ...
Hit any key to stop autoboot: 0
-
MMC read: dev # 0, block # 2048, count 8192 partition # 0 ...
8192 blocks read: OK
-
MMC read: dev # 0, block # 12288, count 768 partition # 0 ...
768 blocks read: OK
## Booting kernel from Legacy Image at 70800000 ...
Image Name: Linux-2.6.35.3-hg9facadc85de9-di
Created: 2013-01-25 7:01:22 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3346940 Bytes = 3.2 MB
Load Address: 70008000
Entry Point: 70008000
Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 70d00000 ...
Image Name: ntxinitramfs
Created: 2013-02-05 5:38:45 UTC
Image Type: ARM Linux RAMDisk Image (uncompressed)
Data Size: 145089 Bytes = 141.7 kB
Load Address: 70308000
Entry Point: 70308000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
...................................
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Initializing cgroup subsys cpu
Linux version 2.6.35.3-hg9facadc85de9-dirty (antony@antony-desktop) (gcc version 4.4.3 (GCC) ) #168 PREEMPT Fri Jan 25 15:01:19 CST 2013
CPU: ARMv7 Processor [412fc085] revision 5 (ARMv7), cr=10c53c7f
...................................

Of course – you can interrupt the boot process by pressing a key.. here comes the output of printenv and bdinfo:


eBR-1A # printenv
bootdelay=1
baudrate=115200
loadaddr=0x70800000
netdev=eth0
ethprime=FEC0
uboot=u-boot.bin
kernel=uImage
nfsroot=/opt/eldk/arm
bootargs_base=setenv bootargs console=ttymxc0,115200
bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
bootcmd_net=run bootargs_base bootargs_nfs; tftpboot ${loadaddr} ${kernel}; bootm
bootargs_mmc=setenv bootargs ${bootargs} ip=dhcp root=/dev/mmcblk0p2 rootwait
bootcmd_mmc=run bootargs_base bootargs_mmc; bootm
rd_loadaddr=0x70D00000
bootcmd_SD=mmc read 0 ${loadaddr} 0x800 0x2000; mmc read 0 ${rd_loadaddr} 0x3000 0x300;
bootcmd=run bootcmd_SD; bootm ${loadaddr} ${rd_loadaddr}
bootargs=console=ttymxc0 init=/init androidboot.console=ttymxc0 keypad video=mxc_elcdif_fb:off calibration
stdin=serial
stdout=serial
stderr=serial
-
eBR-1A # bdinfo
arch_number = 0x00000BAC
env_t       = 0x00000000
boot_params = 0x70000100
DRAM bank   = 0x00000000
-&gt; start    = 0x70000000
-&gt; size     = 0x10000000
baudrate    = 115200 bps

You can download the complete bootlog here: tolino_shine_boot_log.txt

After booting you are put to a bash shell but the console is cluttered by a continuously stream of some redraw informations and the logging of temperature state of the display voltage controller. If you are lucky you can get some clean output…

bash-3.2# ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 324 188 800ec05c 0000875c S /init
root 2 0 0 0 800823d8 00000000 S kthreadd
root 3 2 0 0 80071a24 00000000 S ksoftirqd/0
root 4 2 0 0 8007ec3c 00000000 S events/0
root 5 2 0 0 8007ec3c 00000000 S khelper
root 8 2 0 0 800890f0 00000000 S async/mgr
root 9 2 0 0 8007ec3c 00000000 S pm
root 12 2 0 0 8007ec3c 00000000 S suspend
root 76 2 0 0 80057a2c 00000000 S usb_wakeup thre
root 77 2 0 0 80057a2c 00000000 S usb_wakeup thre
root 234 2 0 0 800bb414 00000000 S sync_supers
root 236 2 0 0 800bbef4 00000000 S bdi-default
root 238 2 0 0 8007ec3c 00000000 S kblockd/0
root 252 2 0 0 8007ec3c 00000000 S mxc_spi.2
root 259 2 0 0 8007ec3c 00000000 S otg_switch/0
root 265 2 0 0 8029d5c8 00000000 S khubd
root 282 2 0 0 8007ec3c 00000000 S kmmcd
root 312 2 0 0 8031c4d4 00000000 S pmic-event-thre
root 336 2 0 0 8007ec3c 00000000 S rpciod/0
root 345 1 0 0 80051524 00000000 D swapper
root 350 2 0 0 8007ec3c 00000000 S zq_calib
root 356 2 0 0 800b5abc 00000000 S kswapd0
root 404 2 0 0 8007ec3c 00000000 S aio/0
root 414 2 0 0 8007ec3c 00000000 S nfsiod
root 418 2 0 0 8007ec3c 00000000 S crypto/0
root 446 2 0 0 8007ec3c 00000000 S submit/0
root 457 2 0 0 8007ec3c 00000000 S tps65185_PWRGOO
root 459 2 0 0 8007ec3c 00000000 S tps65185_INT/0
root 1039 2 0 0 802346f8 00000000 S kapmd
root 1105 2 0 0 802c4260 00000000 S file-storage
root 1149 2 0 0 8007ec3c 00000000 S kstriped
root 1154 2 0 0 8007ec3c 00000000 S kconservative/0
root 1157 2 0 0 8007ec3c 00000000 S mxc_chg
root 1158 2 0 0 8007ec3c 00000000 S mc13892_battery
root 1165 2 0 0 8007ec3c 00000000 S esdhc_wq/0
root 1170 2 0 0 8007ec3c 00000000 S esdhc_wq/0
root 1172 2 0 0 8007ec3c 00000000 S esdhc_wq/0
root 1182 2 0 0 8007ec3c 00000000 S usbhid_resumer
root 1185 2 0 0 8007ec3c 00000000 S binder
root 1217 2 0 0 8007ec3c 00000000 S l2cap
root 1218 2 0 0 80459624 00000000 S krfcommd
root 1226 1 300 156 800ec05c 0000875c S /sbin/ueventd
root 1243 2 0 0 80336e9c 00000000 S mmcqd
root 1309 446 0 0 8006ff84 00000000 Z submit/0
root 2013 2 0 0 80336e9c 00000000 S mmcqd
root 2015 2 0 0 8015c29c 00000000 S jbd2/mmcblk0p2-
root 2018 2 0 0 8007ec3c 00000000 S ext4-dio-unwrit
root 2019 2 0 0 800fbf4c 00000000 S flush-179:0
root 2020 2 0 0 8015c29c 00000000 S jbd2/mmcblk0p5-
root 2021 2 0 0 8007ec3c 00000000 S ext4-dio-unwrit
root 2022 2 0 0 8015c29c 00000000 S jbd2/mmcblk0p6-
root 2023 2 0 0 8007ec3c 00000000 S ext4-dio-unwrit
root 2024 1 1428 780 8006f710 000a8fa8 S /system/bin/bash
system 2025 1 816 256 8034b580 6fd0b6fc S /system/bin/servicemanager
root 2026 1 3868 588 ffffffff 6fd0bdac S /system/bin/vold
root 2027 1 3844 560 ffffffff 6fd0bdac S /system/bin/netd
root 2028 1 820 324 800ec05c 6fd0b844 S /system/bin/dispd
root 2029 1 676 260 803834dc 6fd0c0cc S /system/bin/debuggerd
root 2030 1 99812 27668 800ec05c 6fd0b844 S zygote
media 2031 1 17216 4212 ffffffff 6fd0b6fc S /system/bin/mediaserver
root 2032 1 824 316 804057bc 6fd0b45c S /system/bin/installd
keystore 2033 1 1752 428 803834dc 6fd0c0cc S /system/bin/keystore
shell 2036 1 3400 164 ffffffff 00008294 S /sbin/adbd
system 2088 2030 165876 36432 ffffffff 6fd0b6fc S system_server
app_3 2140 2030 116008 20024 ffffffff 6fd0c51c S com.android.inputmethod.latin
system 2146 2030 108160 14940 ffffffff 6fd0c51c S ntx.power
system 2152 2030 113392 24008 ffffffff 6fd0c51c S com.android.systemui
system 2153 2030 138684 35756 ffffffff 6fd0c51c S de.telekom.epub
app_6 2192 2030 112424 19224 ffffffff 6fd0c51c S android.process.acore
app_4 2220 2030 111196 17944 ffffffff 6fd0c51c S android.process.media
app_5 2230 2030 108752 16912 ffffffff 6fd0c51c S com.android.providers.calendar
root 2250 2 0 0 800fbf4c 00000000 S flush-179:8
root 2257 2024 904 316 00000000 6fd0b45c R ps

And btw – about „rooting“ that device:


bash-3.2# id
uid=0(root) gid=1007(log)

I also tried to get some data from the remaining serial ports – but nothing happens here. Maybe they use a protocol based on polling or they are not for reading data bur for programming the two MSP430 processors… follow the traces and tell us if you found something great…

ADB

I made some changes on the SD card to enable ADB by activating some uncommented lines in /system/bin/upgrade_check.sh. Remember – this file was one of my first findings in the beginning of the journey. It gives me some (late) satisfaction to use that file (even if I had to open the Shine for it – and of curse, there are other ways to do that – just remove the disabled flag for the ADB service…)

# xiaobo begin of adb_open
elif [ -e /mnt/sdcard/extsd/adb_open ]; then
setprop persist.service.adb.enable 1
sync
sync
elif [ -e /mnt/sdcard/extsd/adb_close ]; then
setprop persist.service.adb.enable 0
sync
sync
xiaobo end of adb open

After that I touched a file named adb_open to /sdcard/extsd. If you had a look at the boot-log you already found a line containing the following:


warning: `adbd' uses 32-bit capabilities (legacy support in use)
enabling adb

I can’t give you any information about using ADB in windows. But if you are running Linux you are fine eg. under Ubuntu sudo apt-get install android-tools-adb will provide you with the needed tool. If not and your distro does not offer a package that contains ADB go and download the right part from the  Android SDK. Good luck.

If you have installed ADB the remaining part is straight forward:


# get the vendor id from syslog (maybe dmesg | grep idVendor): idVendor=1f85 then...
#&gt; echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1f85", MODE="0666", GROUP="plugdev"' &gt;&gt; /etc/udev/rules.d/51-android.rules
#&gt; mkdir ~/.android/
#&gt; echo 0x1f85 &gt; ~/.android/adb_usb.ini
#&gt; adb server-start
#&gt; adb devices
-
List of devices attached
20030394 device
-
#&gt; adb shell
$ ls
config
cache
sdcard
acct
mnt
vendor
d
etc
sys
init.rc
ueventd.rc
default.prop
sbin
init.goldfish.rc
ueventd.freescale.rc
system
ueventd.goldfish.rc
data
init
proc
init.freescale.rc
root
dev
....

The rest is up to you. With ADB enabled you could close the enclosure and use USB for communication… just use the serial line to remove permission restrictions before:)

next steps

Exploring the Tolino Shine was fun. I ended up with a device that was opened… not really rooted by using some software – some special kind of escalation. But looking for a JTAG interface and finding an easy to change SD card is… win. Having ADB and serial connection now is nothing to be proud of – it was inside the device all the time. And to be honest: I feel a little bit sad that I was not able to achieve at least the working ADB without opening the device. Now some scripts have to be done to enable ADB all the time and remove all permission restrictions on that device (and: publish new SD images!). Maybe someone could change the Public Key (one is located in the recovery partition – just look for key, use the informations about creating keys and the key file out of this ) in the image by on of a well known keypair… a lot of stuff if you like to continue in a eco system called „Tolino Shine“. For me the device is now just an easy to change and powerful system with a excellent touch screen, a serial port and more or less space inside the enclosure to add new hardware. So there are two big possibilities to continue on:

  • analyzing the system by looking at the whole system description – in hard- and software, find the weak point and root the device without opening it
  • create your own system running on the shines hardware

The latter one is the way I choose – the goal is a sd card image that holds all the stuff to run the shine as piratebox… But with the announcement of new Tolino hardware for the end of 2013 the price should go down… more Shines, more developers… Lets see what happens. Good luck!

relevant links

hardware:
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=IMX50EVK

ARM knowledege base:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/

Porting kernel to arm:
http://www.linux-arm.org/pub/LinuxKernel/WebHome/aleph-porting.pdf

freescale downloads:
http://git.freescale.com/git/

ARM toolchain:
https://wiki.linaro.org/Resources/ToolchainInstall-10/4.4
http://www.linaro.org/downloads/
https://github.com/AdiPat/Android_Toolchains

uboot:
http://www.compulab.co.il/workspace/mediawiki/index.php5/U-Boot:_Images
http://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/

qemu – arm:
http://www.linuxforu.com/2011/06/qemu-for-embedded-systems-development-part-1/
http://wiki.qemu.org/Download
http://balau82.wordpress.com/2010/03/22/compiling-linux-kernel-for-qemu-arm-emulator/
http://mmmyddd.freeshell.net/wiki/embed/linuxonarmonqemu.html
http://qemu.weilnetz.de/qemu-doc.html#ARM-System-emulator
https://wiki.edubuntu.org/ARM/RootfsFromScratch/QemuDebootstrap

problems with ARM on qemu:
https://community.freescale.com/thread/281256

good intro about using gdb with qemu to debug a running system:
http://files.meetup.com/1590495/debugging-with-qemu.pdf

kernel debug:
https://www.kernel.org/doc/htmldocs/kgdb/EnableKGDB.html
http://elinux.org/Debugging_by_printing#Debugging_early_boot_problems

gdb kernel stub:
http://wiki.osdev.org/GDB

android ndk download:
http://developer.android.com/tools/sdk/ndk/index.html

.apk – run and reverse:
http://stackoverflow.com/questions/4512458/androidhow-to-run-apk-file-on-emulator
https://code.google.com/p/android-apktool/

android security:
http://www.ibm.com/developerworks/library/x-androidsecurity/

android filesystem overview:
http://anantshri.info/andro/file_system.html

android – relevant sources:
https://android.googlesource.com/platform/bootable/recovery/+/master/bootloader.cpp
https://android.googlesource.com/platform/bootable/recovery/+/master/verifier.cpp
https://android.googlesource.com/platform/bootable/recovery/+/master/install.cpp

update.zip:
http://images.thalia.de/md2/ereader/update/update.zip
http://www.sslshopper.com/certificate-decoder.html
http://www.londatiga.net/it/how-to-sign-apk-zip-files/
http://developer.android.com/tools/publishing/app-signing.html

keys & co – tools, infos:
https://raw.github.com/cgjones/android-system-core/master/libmincrypt/tools/DumpPublicKey.java
http://www.bouncycastle.org/latest_releases.html
http://en.wikipedia.org/wiki/RSA_%28algorithm%29

uRamdisk, initrd & co:
http://forum.xda-developers.com/showthread.php?t=1477845
http://www.glomationinc.com/doc/HowToEditRAMDisk.PDF
http://www.isysop.com/unpacking-and-repacking-u-boot-uimage-files/
http://www.unixboard.de/vb3/showthread.php?5913-initrd-img-bearbeiten

CVE:

http://www.cvedetails.com/product/19997/Google-Android.html?vendor_id=1224
http://www.cvedetails.com/cve/CVE-2010-4804/
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-1807
http://thomascannon.net/blog/2010/11/android-data-stealing-vulnerability/

other readers but related:
http://pastie.org/pastes/6112039

pagetop