Close

Dumping the external flash

A project log for Color Open Source Smartwatch

Reverse engineering the SMA-Q2 smartwatch to run open source firmware on it

emerythemeryth 03/13/2018 at 19:141 Comment

Yesterday I dumped the external flash. You can find the image in the owncloud archive.
Turns out most of it is used to store an almost complete 16-bit Unicode font.

I figured that out by converting the binary to an image and looking for repeating or familiar patterns.
A good tool for that is ImageMagick.

With the following command:

convert -depth 1 -size 16x2048 gray:flash_dump.bin flash.png 

you can turn the binary into binary (heh) images.

Using a width of 16 pixels reveals that most of the space is taken by a font.

But you can see that some of the characters are messed up. It's not a problem with the dump or some offset, the problems clearly happen on smaller characters, so the font must not be of fixed 16x16 size. We cannot decode the glyphs without knowing their width!

In memory, the glyphs follow a rather large area with some other data, it must be some kind data structure for the font, perhaps with info about the width of every character.

0000:2000 | 55 46 4C 11  54 F0 12 00  01 10 FF 3F  62 77 00 00 | UFL.Tð....ÿ?bw..
0000:2010 | 20 00 E6 FF  18 00 00 00  34 FF 03 10  44 FF 03 10 |  .æÿ....4ÿ..Dÿ..
0000:2020 | 54 FF 03 18  64 FF 03 24  84 FF 03 24  A4 FF 03 38 | Tÿ..dÿ.$.ÿ.$¤ÿ.8

The data starts with a magic header "UFL", unfortunately, even with that, I was unable to find any info about this font format.

So I had to dig deeper.



The strings in the original watch firmware refer to something called 'arialuni_U16.bin'.
That turns out to be a font file with unicode characters used by a Chinese modification for GRUB4DOS.
When I downloaded the file from Google Code it turned out to be of the same binary format! (not identical though)

Lots of searching and translating later I have found what seems to be a blog of the author of a Chinese font creation tool called FontMaker that seems to be the source of the format.

There I found a simple explanation (that google translates amazingly well) of the format:

http://blog.sina.com.cn/s/blog_5d8cc6410100dkko.html

C. Unicode

00000000h: 55 46 4C 10 28 AB 07 00 01 10 81 00 00 00 00 00
00000010h: 20 00 FF FF 18 00 00 00 98 FF 03 10 A8 FF 03 10
...
0003ff90h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0003ffa0h: 00 00 00 00 00 00 00 00 00 00 40 40 40 40 40 40
0003ffb0h: 40 40 00 40 40 00 00 00 00 48 48 48 48 00 00
...


Analyze as follows:
1). File header (first 16 Byte)

55 46 4C 10 -- Marker to determine if it is a valid font file.
55 = 'U', indicates that the file is a font file in unicode encoding format.
46 = 'F', 4C = 'L'
10 indicates that the font file version information is: Version 1.0
28 AB 07 00 -- Total file length
01 -- contains several Sections. 1- 1 Section (without CJK, it is divided into 3 Sections)
10 -- font height 0x10 == 16
81 00 -- The selected character set flag. 1-ID selection, 0-ID not selected. Therefore, the current selection is: Japanese + Western European character set.
00 00 00 00 -- reserved bytes

2). Segment information (n section * sizeof(FL_SECTION_INF) = 1 * 8 = 8))
20 00 -- First character
FF FF -- Last character
18 00 00 00 -- OffAddr;

3). Search table ((Section[0].Last - Section[0].First + 1) * 4 + (Section[n-1].Last - Section[n-1].First + 1) * 4)
Each 4 bytes represents one character of search information, starting with the character Section[0].First. So the character 0x20 search information (start address =
(character unicode code - Section[x].First) × 4 + Section[x].OffAddr, x is the current section character in the section index value, can be judged. ): 98 FF 03 10
That is, a 32-bit number is obtained: 0x1003FF98 (hexadecimal) --- (00010000 00000011 11111111 10011000).
The high 6 indicates the width of the current character. Therefore, we get 000100 -- 4 (font size is 4)
The lower 26 bits indicate the offset address of the dot matrix information of the current character. Therefore, we get 0000000011 11111111 10011000 -- 0x3FF98 (starting address of dot matrix information is 0x3FF98)

3). Bitmap information
Since the start address of the space character is 0x3FF98 and the data length is: ((font width +7)/8)* font height = ((4+7)/8)*16 = 16.
So take the following 16 bytes, which is a dot character dot matrix information.
0003ff98h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

The same as the following is the bit information of the character 0x21.
0003ffA8h: 00 00 40 40 40 40 40 40 40 40 00 40 40 00 00 00

Here are some code references:

https://github.com/chenall/grubutils/blob/master/g4dext/font/Unicode/unicode.c
https://github.com/chenall/grubutils/blob/master/g4dext/font/font.h
https://github.com/kagajubo/multi-lang/blob/master/utility/demo/font/font.c

As I suspected, the data structure contains the width and address of every single character.


The font accounts for about 1.2MB of the 2MB flash.
What's in the rest, I have no idea.

I suspected it contains the downloadable watchfaces, but I could not confirm that.

Discussions

ddavidmelo wrote 03/14/2018 at 21:44 point

I have this watch and I think with a good firmware can be better than pebble. Keep going with this work, I would love to see the something cool in the end.

  Are you sure? yes | no