Skip to content

Instantly share code, notes, and snippets.

@Doliman100
Last active March 17, 2024 16:20
Show Gist options
  • Select an option

  • Save Doliman100/c4d22766c4288ad0e025fb3eba066289 to your computer and use it in GitHub Desktop.

Select an option

Save Doliman100/c4d22766c4288ad0e025fb3eba066289 to your computer and use it in GitHub Desktop.
Xiaomi Smart Band 8 firmware and watchface package template for 010 Editor.
//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
// File: updata_pack.bin.bt
// Authors:
// Version:
// Purpose:
// Category:
// File Mask: *.bin
// ID Bytes: 78 56 34 12
// History:
//------------------------------------------------
uint magic <format=hex, comment="0x12345678">;
uint unknown;
uint type <comment="1 - diff, 2 - full">;
char new_version[64];
char old_version[64];
uint components_offset;
uint size; // file_size excluding sign
uint components_count;
uint unknown;
local uint component_offset = components_offset;
struct ComponentInfo {
uint patch_size;
uint size;
ushort id;
uchar flag <comment="1">;
uchar patch_type <comment="1 - diff, 2 - full">;
char new_version[64]; // "", "2.2.12"
char old_version[64]; // "2.1.8"
uint patch_crc <format=hex, comment="CRC-32">;
if (flag == 1) {
Printf("%08x - %08x %08x %2d\r\n", component_offset, component_offset + patch_size, patch_size, id);
local uint pos = FTell();
FSeek(component_offset);
if (patch_type == 1) {
struct {
// https://patents.google.com/patent/CN105786563B/zh
struct {
char header[8] <comment="ROCKDIFF">;
uint source_rom_len;
uint target_rom_len;
uint source_hash <format=hex, comment="Adler-32">;
uint target_hash <format=hex, comment="Adler-32">;
int chunk_number;
uchar unknown[44];
} IOT_DELTA_HEADER;
struct {
int type; // CHUNK_DIFF, CHUNK_RAW
uint source_base;
uint source_len;
uint target_base;
uint target_len;
uint patch_len;
uint patch_offset;
uint source_hash <format=hex, comment="Adler-32">;
uint target_hash <format=hex, comment="Adler-32">;
uchar unknown[8];
} IOT_DELTA_CHUNK[IOT_DELTA_HEADER.chunk_number];
} patch <size=patch_size>;
} else {
uchar patch[patch_size];
}
FSeek(pos);
component_offset += patch_size;
}
} component_info[25] <optimize=false, read=PrintComponentInfo>;
string PrintComponentInfo(ComponentInfo &component_info) {
local string s;
switch (component_info.id) {
case 1:
s = "#bootloader";
break;
case 2:
s = "/yaffs2_mount/safemode/safe.bin";
break;
case 3:
s = "#rom";
break;
case 4:
s = "/yaffs2_mount/ui/img_s.bin";
break;
case 5:
s = "/yaffs2_mount/ui/img_d.bin";
break;
case 6:
s = "/yaffs2_mount/ui/dynamic_font.bin";
break;
case 7:
s = "/yaffs2_mount/ui/static_font.bin";
break;
case 8:
s = "/yaffs2_mount/ui/static_word.bin";
break;
case 9:
s = "/yaffs2_mount/ui/watchface/base/watchface_01.bin";
break;
case 10:
s = "/yaffs2_mount/ui/watchface/base/watchface_02.bin";
break;
case 11:
s = "/yaffs2_mount/ui/watchface/base/watchface_03.bin";
break;
case 12:
s = "/yaffs2_mount/ui/watchface/base/watchface_04.bin";
break;
case 13:
s = "/yaffs2_mount/ui/watchface/base/watchface_05.bin";
break;
case 14:
s = "/yaffs2_mount/ui/watchface/base/watchface_06.bin";
break;
case 15:
s = "/yaffs2_mount/ui/watchface/base/watchface_07.bin";
break;
case 16:
s = "/yaffs2_mount/ui/watchface/base/event.js";
break;
case 17:
s = "/yaffs2_mount/gps/gps.bin";
break;
case 18:
s = "/yaffs2_mount/firmware/tpfw.bin";
break;
case 19:
s = "/yaffs2_mount/monkey/monkey_json.bin";
break;
case 20:
s = "/yaffs2_mount/firmware/xip_code.bin";
break;
default:
s = "";
break;
}
return s;
}
uint unknown;
FSeek(size);
struct RSA_sign_S {
uint head <format=hex, comment="0xF0F1F2F3">;
uint size;
char data[512] <comment="Base64">;
uint end <format=hex, comment="0xF4F5F6F7">;
} sign;
1 date
1 time
1 hours
2 minutes
3 seconds
4 centiseconds
5 hours in 12-hour format
2 date
1 year
2 month
3 day of the month
4 day of the week
3 misc
1 is AM; AM = 0; PM = 8 or 7
2 ?; AM = 0; PM = month
3 is 12-hour format; AM = 0; PM = day of the month
2 stats
1 steps
1 count
2 percents
2 heart rate
1 BPM
3 calories
1 kcal
2 percents
4 standing
1 hrs
2 percents
6 stress
1 score
8 sleep
1 score
9 moving
1 mins
2 percents
3 weather
1 current
1 temperature unit
4 temperature
5 humidity
6 icon
10 Air Quality Index
4 system
1 status
1 battery percents
2 on charge
3 Do Not Disturb
4 Bluetooth
6 PIN lock
//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
// File: watchface_01.bin.bt
// Authors:
// Version:
// Purpose:
// Category:
// File Mask: *.bin
// ID Bytes: 5A A5 34 12
// History:
//------------------------------------------------
// firmware: Global 2.2.12
// MD5: ab2cc595b8bdf53d16b17a43071695d7
typedef struct {
string buffer;
} String <read=StringToWString(this.buffer, CHARSET_UTF8), write=true>;
enum <uchar> Alignment {
None,
Left,
Center,
Right
};
enum <uint> ObjectType {
ObjectType_Element,
ObjectType_Bitmap = 2,
ObjectType_BitmapList,
ObjectType_Animation, // unsupported: 140BAC38
ObjectType_App,
ObjectType_Widget = 7,
ObjectType_Option, // 0 or 1
ObjectType_ActionButton
};
struct RLEImage (uint size) {
uint signature <format=hex, comment="0x5AA521E0">;
uint alpha_flag : 4;
uint uncompressed_size : 28;
uchar buffer[size - 8]; // size calculation: 140BA496
};
struct Bitmap {
uchar unknown;
uchar unknown : 2;
uchar compression : 2;
uchar unknown : 4;
uchar unknown;
uchar unknown;
ushort width;
ushort height;
uint size;
if (compression) {
RLEImage image(size);
} else {
uchar image[size];
}
};
struct Index {
uint id : 24;
ObjectType type : 8;
};
uint signature <format=hex, comment="0x12345AA5">;
uchar unknown1[12];
uint version <format=hex>; // 0x0701 or 0x0800
uchar unknown2[8];
uchar display_length;
// [0] - Home screen
// [1] - Always-on display
uchar unknown4_length;
ushort unknown; // bitfield
// 2 - has AOD (4, 6)
uint preview_offset; // bitmap
uchar unknown3[4];
char id[64];
// id[4] == 6 (App) or 1 (others); 140BCD44
String title <size=64, comment="UTF-8">;
// header size: 168
if (unknown4_length > 0) {
uint unknown4[unknown4_length];
}
struct {
//uchar unknown[88];
uint unknown;
uint unknown;
struct {
uint length;
uint offset;
//Printf("%08x - %08x %08x\r\n", offset, offset + 16 * count, 16 * count);
if (length > 0) {
local uint pos = FTell();
FSeek(offset);
struct {
Index index;
uint unknown3;
uint offset;
uint size;
//Printf("%08x - %08x %d %d\r\n", offset, offset + size, index.type, size);
//Printf("%d\t%d\t%d\t%d\t%d\t%d\r\n", offset, offset + size, unknown[1] == 2024, index.type, index.id, size);
local int pos = FTell();
FSeek(offset);
switch (index.type) {
case ObjectType_Element:
struct {
Index target_index;
ushort pos_x;
ushort pos_y;
uchar unknown[8];
//Printf(" %d %d %d %d\r\n", target_index.type, target_index.id, pos_x, pos_y);
} data;
break;
case ObjectType_Bitmap:
Bitmap data;
break;
case ObjectType_BitmapList:
struct BitmapList {
uchar unknown;
uchar image_length; // max: 40
uchar unknown : 2;
uchar compression : 2;
uchar unknown : 4;
uchar unknown;
ushort width;
ushort height;
uint size;
if (compression) {
uint image_size[image_length];
local int i;
for (i = 0; i < image_length; i++) {
RLEImage image(image_size[i]);
}
} else {
uint images[width * height * image_length];
}
} data; // C++ struct size: 184
break;
// case ObjectType_App: // C++ struct size: 8
case ObjectType_Widget:
struct {
struct {
ushort digit : 3; // 0 - all
ushort subtype : 5;
ushort type : 4;
ushort category : 4;
//Printf("%d %d %d %d\r\n", category, type, subtype, digit);
} value_source <read=Str("%d.%d.%d (%d)", category, type, subtype, digit)>;
uchar digits;
Alignment alignment : 2;
uchar pad : 1; // left-pad with zeroes
uchar unknown : 1;
uchar type_id : 4;
// 1 number box
// 2 image list
// 4 circular progress bar
// 5 linear progress bar
uint unknown;
switch (type_id) {
case 1:
Index digit_list_index;
uint unknown;
Index symbol_index;
break;
case 2:
Index image_list_index;
uint unknown : 9;
uint overwrite_index : 1;
uint unknown : 22;
if (overwrite_index) {
uint index[(size - 16) / 4];
}
break;
case 4:
Index foreground_index;
Index background_index;
break;
default:
Index target_index;
break;
}
//Printf(" %d %d\r\n", target_index.type, target_index.id);
} data <size=size>;
/*Printf(" ");
struct {
local int i;
for (i = 0; i < size; i++) {
uchar data;
Printf("%02X", data);
}
} data;
Printf("\r\n");*/
break;
case ObjectType_Option:
struct {
uchar length;
uchar __padding__[3];
Index target_index[length];
} data;
break;
case ObjectType_ActionButton:
struct {
uchar unknown_1[40];
ushort length;
ushort unknown;
//Printf(" ");
struct {
ushort pos_x;
ushort pos_y;
Index widget_index;
//Printf("%d %d, ", widget_index.type, widget_index.id);
} unknown1[length] <optimize=false>;
//Printf("\r\n");
} data;
break;
default:
uchar data[size];
break;
}
FSeek(pos);
} object[length] <optimize=false>; // size: 16
FSeek(pos);
}
} object_by_type[10] <optimize=false>;
} display[display_length] <optimize=false>; // size: 88
// memset
// 168
// 88 * file[28]
// 16 * accumulate
FSeek(preview_offset);
Bitmap preview;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment