From 69df56504e7dfc8ba7e283901aadde6ebdada5b1 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Wed, 13 Aug 2014 12:46:45 +0200 Subject: hwpatcher: add framework for CRC computation Change-Id: Ib78f0fe58db5cec86f043d3e9e1ca14e69297ba0 Reviewed-on: http://gerrit.rockbox.org/911 Reviewed-by: Marcin Bukat --- utils/hwpatcher/hwpatcher.c | 85 +++++++++++++++++++++++++++++++++++++++++++++ utils/hwpatcher/lib.lua | 32 +++++++++++------ 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/utils/hwpatcher/hwpatcher.c b/utils/hwpatcher/hwpatcher.c index 60e142bbc1..7153a220c9 100644 --- a/utils/hwpatcher/hwpatcher.c +++ b/utils/hwpatcher/hwpatcher.c @@ -47,6 +47,8 @@ #include "misc.h" #include "md5.h" +#define ARRAYLEN(arr) (sizeof(arr) / sizeof(arr[0])) + lua_State *g_lua; bool g_exit = false; @@ -59,6 +61,18 @@ enum fw_type_t FW_UNK, FW_ELF, FW_SB1, FW_SB2, FW_BIN, FW_EDOC }; +enum crc_type_t +{ + CRC_RKW +}; + +struct crc_type_desc_t +{ + enum crc_type_t type; + const char *lua_name; + unsigned (*fn)(uint8_t *buf, size_t len); +}; + struct bin_file_t { size_t size; @@ -849,6 +863,66 @@ int my_lua_section_info(lua_State *state) return 1; } +unsigned crc_rkw(uint8_t *buf, size_t len) +{ + /* polynomial 0x04c10db7 */ + static const uint32_t crc32_lookup[16] = + { /* lookup table for 4 bits at a time is affordable */ + 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9, + 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005, + 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61, + 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD + }; + + uint32_t crc32 = 0; + unsigned char byte; + uint32_t t; + + while (len--) + { + byte = *buf++; /* get one byte of data */ + + /* upper nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + + /* lower nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + } + + return crc32; +} + +struct crc_type_desc_t crc_types[] = +{ + {CRC_RKW, "RKW", crc_rkw} +}; + +int my_lua_crc_buf(lua_State *state) +{ + int n = lua_gettop(state); + if(n != 2) + return luaL_error(state, "crc_buf takes two arguments: a crc type and a buffer"); + unsigned type = lua_tounsigned(state, 1); + size_t len; + void *buf = my_lua_get_buffer(state, 2, &len); + for(int i = 0; i < ARRAYLEN(crc_types); i++) + if(crc_types[i].type == type) + { + lua_pushunsigned(state, crc_types[i].fn(buf, len)); + free(buf); + return 1; + } + free(buf); + luaL_error(state, "crc_buf: unknown crc type"); + return 0; +} + /* compute MD5 sum of a buffer */ static bool compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16]) { @@ -945,6 +1019,17 @@ static bool init_lua_hwp(void) lua_pushcfunction(g_lua, my_lua_md5sum); lua_setfield(g_lua, -2, "md5sum"); + lua_newtable(g_lua); + for(int i = 0; i < ARRAYLEN(crc_types); i++) + { + lua_pushunsigned(g_lua, crc_types[i].type); + lua_setfield(g_lua, -2, crc_types[i].lua_name); + } + lua_setfield(g_lua, -2, "CRC"); + + lua_pushcfunction(g_lua, my_lua_crc_buf); + lua_setfield(g_lua, -2, "crc_buf"); + return true; } diff --git a/utils/hwpatcher/lib.lua b/utils/hwpatcher/lib.lua index 7a3e4a4115..4c0d6ff7ab 100644 --- a/utils/hwpatcher/lib.lua +++ b/utils/hwpatcher/lib.lua @@ -8,16 +8,21 @@ At global level: - exit() Same as quit() In the hwp table: -- load_file(filename) Load a firmware and guess type -- load_elf_file(filename) Load a firmware as ELF -- load_sb_file(filename) Load a firmware as SB -- load_sb1_file(filename) Load a firmware as SB1 -- load_bin_file(filename) Load a firmware as binary -- save_file(obj, filename) Save a firmware to a file -- read(obj, addr, len) Read data from a firmware -- write(obj, addr, data) Write data to a firmware -- section_info(obj, sec) Return information about a section in a table (or nil) -- md5sum(filename) Compute the MD5 sum of a file +- load_file(filename) Load a firmware and guess type +- load_elf_file(filename) Load a firmware as ELF +- load_sb_file(filename) Load a firmware as SB +- load_sb1_file(filename) Load a firmware as SB1 +- load_bin_file(filename) Load a firmware as binary +- save_file(fw, filename) Save a firmware to a file +- read(fw, addr, len) Read data from a firmware +- write(fw, addr, data) Write data to a firmware +- section_info(fw, sec) Return information about a section in a table (or nil) +- md5sum(filename) Compute the MD5 sum of a file +- crc_buf(crc_type, buf) Compute the CRC of a byte buffer and return a byte buffer +- crc(crc_type, fw, addr, len) Compute the CRC of a firmware part + +The list of CRCs available is available the hwp.CRC table: +- RKW Data read/written from/to a firmware must must be an array of bytes. The address must be a table of the following fields: @@ -27,7 +32,7 @@ Data section information is a table with the following fields: - address: first address if the section - size: size of the section We provide the following functions to help dealing with addresses: -- make_addr +- make_addr(addr, section) Build a firmware address from a raw address and a section ]]-- @@ -105,3 +110,8 @@ function hwp.md5str(md5) end return s end + +-- compute the CRC of a firmware part +function hwp.crc(crc_type, fw, addr, len) + return hwp.crc_buf(crc_type, hwp.read(fw, addr, len)) +end -- cgit v1.2.3