1*23ba6841SJoseph Chen // SPDX-License-Identifier: GPL-2.0+ 2*23ba6841SJoseph Chen /* 3*23ba6841SJoseph Chen * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd 4*23ba6841SJoseph Chen */ 5*23ba6841SJoseph Chen 6*23ba6841SJoseph Chen #include <errno.h> 7*23ba6841SJoseph Chen #include <memory.h> 8*23ba6841SJoseph Chen #include <stdint.h> 9*23ba6841SJoseph Chen #include <stdio.h> 10*23ba6841SJoseph Chen #include <stdlib.h> 11*23ba6841SJoseph Chen #include <stdbool.h> 12*23ba6841SJoseph Chen #include <sys/stat.h> 13*23ba6841SJoseph Chen #include <time.h> 14*23ba6841SJoseph Chen 15*23ba6841SJoseph Chen /* #define DEBUG */ 16*23ba6841SJoseph Chen 17*23ba6841SJoseph Chen static bool g_debug = 18*23ba6841SJoseph Chen #ifdef DEBUG 19*23ba6841SJoseph Chen true; 20*23ba6841SJoseph Chen #else 21*23ba6841SJoseph Chen false; 22*23ba6841SJoseph Chen #endif /* DEBUG */ 23*23ba6841SJoseph Chen 24*23ba6841SJoseph Chen #define LOGE(fmt, args...) \ 25*23ba6841SJoseph Chen fprintf(stderr, "E/%s(%d): " fmt "\n", __func__, __LINE__, ##args) 26*23ba6841SJoseph Chen #define LOGD(fmt, args...) \ 27*23ba6841SJoseph Chen do { \ 28*23ba6841SJoseph Chen if (g_debug) \ 29*23ba6841SJoseph Chen fprintf(stderr, "D/%s(%d): " fmt "\n", __func__, __LINE__, ##args); \ 30*23ba6841SJoseph Chen } while (0) 31*23ba6841SJoseph Chen 32*23ba6841SJoseph Chen /* sync with ./board/rockchip/rk30xx/rkloader.c #define FDT_PATH */ 33*23ba6841SJoseph Chen #define FDT_PATH "rk-kernel.dtb" 34*23ba6841SJoseph Chen #define DTD_SUBFIX ".dtb" 35*23ba6841SJoseph Chen 36*23ba6841SJoseph Chen #define DEFAULT_IMAGE_PATH "resource.img" 37*23ba6841SJoseph Chen #define DEFAULT_UNPACK_DIR "out" 38*23ba6841SJoseph Chen #define BLOCK_SIZE 512 39*23ba6841SJoseph Chen 40*23ba6841SJoseph Chen #define RESOURCE_PTN_HDR_SIZE 1 41*23ba6841SJoseph Chen #define INDEX_TBL_ENTR_SIZE 1 42*23ba6841SJoseph Chen 43*23ba6841SJoseph Chen #define RESOURCE_PTN_VERSION 0 44*23ba6841SJoseph Chen #define INDEX_TBL_VERSION 0 45*23ba6841SJoseph Chen 46*23ba6841SJoseph Chen #define RESOURCE_PTN_HDR_MAGIC "RSCE" 47*23ba6841SJoseph Chen typedef struct { 48*23ba6841SJoseph Chen char magic[4]; /* tag, "RSCE" */ 49*23ba6841SJoseph Chen uint16_t resource_ptn_version; 50*23ba6841SJoseph Chen uint16_t index_tbl_version; 51*23ba6841SJoseph Chen uint8_t header_size; /* blocks, size of ptn header. */ 52*23ba6841SJoseph Chen uint8_t tbl_offset; /* blocks, offset of index table. */ 53*23ba6841SJoseph Chen uint8_t tbl_entry_size; /* blocks, size of index table's entry. */ 54*23ba6841SJoseph Chen uint32_t tbl_entry_num; /* numbers of index table's entry. */ 55*23ba6841SJoseph Chen } resource_ptn_header; 56*23ba6841SJoseph Chen 57*23ba6841SJoseph Chen #define INDEX_TBL_ENTR_TAG "ENTR" 58*23ba6841SJoseph Chen #define MAX_INDEX_ENTRY_PATH_LEN 256 59*23ba6841SJoseph Chen typedef struct { 60*23ba6841SJoseph Chen char tag[4]; /* tag, "ENTR" */ 61*23ba6841SJoseph Chen char path[MAX_INDEX_ENTRY_PATH_LEN]; 62*23ba6841SJoseph Chen uint32_t content_offset; /* blocks, offset of resource content. */ 63*23ba6841SJoseph Chen uint32_t content_size; /* bytes, size of resource content. */ 64*23ba6841SJoseph Chen } index_tbl_entry; 65*23ba6841SJoseph Chen 66*23ba6841SJoseph Chen #define OPT_VERBOSE "--verbose" 67*23ba6841SJoseph Chen #define OPT_HELP "--help" 68*23ba6841SJoseph Chen #define OPT_VERSION "--version" 69*23ba6841SJoseph Chen #define OPT_PRINT "--print" 70*23ba6841SJoseph Chen #define OPT_PACK "--pack" 71*23ba6841SJoseph Chen #define OPT_UNPACK "--unpack" 72*23ba6841SJoseph Chen #define OPT_TEST_LOAD "--test_load" 73*23ba6841SJoseph Chen #define OPT_TEST_CHARGE "--test_charge" 74*23ba6841SJoseph Chen #define OPT_IMAGE "--image=" 75*23ba6841SJoseph Chen #define OPT_ROOT "--root=" 76*23ba6841SJoseph Chen 77*23ba6841SJoseph Chen #define VERSION "2014-5-31 14:43:42" 78*23ba6841SJoseph Chen 79*23ba6841SJoseph Chen typedef struct { 80*23ba6841SJoseph Chen char path[MAX_INDEX_ENTRY_PATH_LEN]; 81*23ba6841SJoseph Chen uint32_t content_offset; /* blocks, offset of resource content. */ 82*23ba6841SJoseph Chen uint32_t content_size; /* bytes, size of resource content. */ 83*23ba6841SJoseph Chen void *load_addr; 84*23ba6841SJoseph Chen } resource_content; 85*23ba6841SJoseph Chen 86*23ba6841SJoseph Chen typedef struct { 87*23ba6841SJoseph Chen int max_level; 88*23ba6841SJoseph Chen int num; 89*23ba6841SJoseph Chen int delay; 90*23ba6841SJoseph Chen char prefix[MAX_INDEX_ENTRY_PATH_LEN]; 91*23ba6841SJoseph Chen } anim_level_conf; 92*23ba6841SJoseph Chen 93*23ba6841SJoseph Chen #define DEF_CHARGE_DESC_PATH "charge_anim_desc.txt" 94*23ba6841SJoseph Chen 95*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_DELAY "delay=" 96*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_LOOP_CUR "only_current_level=" 97*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_LEVELS "levels=" 98*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_LEVEL_CONF "max_level=" 99*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_LEVEL_NUM "num=" 100*23ba6841SJoseph Chen #define OPT_CHARGE_ANIM_LEVEL_PFX "prefix=" 101*23ba6841SJoseph Chen 102*23ba6841SJoseph Chen static char image_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0"; 103*23ba6841SJoseph Chen 104*23ba6841SJoseph Chen static int fix_blocks(size_t size) 105*23ba6841SJoseph Chen { 106*23ba6841SJoseph Chen return (size + BLOCK_SIZE - 1) / BLOCK_SIZE; 107*23ba6841SJoseph Chen } 108*23ba6841SJoseph Chen 109*23ba6841SJoseph Chen static const char *fix_path(const char *path) 110*23ba6841SJoseph Chen { 111*23ba6841SJoseph Chen if (!memcmp(path, "./", 2)) { 112*23ba6841SJoseph Chen return path + 2; 113*23ba6841SJoseph Chen } 114*23ba6841SJoseph Chen return path; 115*23ba6841SJoseph Chen } 116*23ba6841SJoseph Chen 117*23ba6841SJoseph Chen static uint16_t switch_short(uint16_t x) 118*23ba6841SJoseph Chen { 119*23ba6841SJoseph Chen uint16_t val; 120*23ba6841SJoseph Chen uint8_t *p = (uint8_t *)(&x); 121*23ba6841SJoseph Chen 122*23ba6841SJoseph Chen val = (*p++ & 0xff) << 0; 123*23ba6841SJoseph Chen val |= (*p & 0xff) << 8; 124*23ba6841SJoseph Chen 125*23ba6841SJoseph Chen return val; 126*23ba6841SJoseph Chen } 127*23ba6841SJoseph Chen 128*23ba6841SJoseph Chen static uint32_t switch_int(uint32_t x) 129*23ba6841SJoseph Chen { 130*23ba6841SJoseph Chen uint32_t val; 131*23ba6841SJoseph Chen uint8_t *p = (uint8_t *)(&x); 132*23ba6841SJoseph Chen 133*23ba6841SJoseph Chen val = (*p++ & 0xff) << 0; 134*23ba6841SJoseph Chen val |= (*p++ & 0xff) << 8; 135*23ba6841SJoseph Chen val |= (*p++ & 0xff) << 16; 136*23ba6841SJoseph Chen val |= (*p & 0xff) << 24; 137*23ba6841SJoseph Chen 138*23ba6841SJoseph Chen return val; 139*23ba6841SJoseph Chen } 140*23ba6841SJoseph Chen 141*23ba6841SJoseph Chen static void fix_header(resource_ptn_header *header) 142*23ba6841SJoseph Chen { 143*23ba6841SJoseph Chen /* switch for be. */ 144*23ba6841SJoseph Chen header->resource_ptn_version = switch_short(header->resource_ptn_version); 145*23ba6841SJoseph Chen header->index_tbl_version = switch_short(header->index_tbl_version); 146*23ba6841SJoseph Chen header->tbl_entry_num = switch_int(header->tbl_entry_num); 147*23ba6841SJoseph Chen } 148*23ba6841SJoseph Chen 149*23ba6841SJoseph Chen static void fix_entry(index_tbl_entry *entry) 150*23ba6841SJoseph Chen { 151*23ba6841SJoseph Chen /* switch for be. */ 152*23ba6841SJoseph Chen entry->content_offset = switch_int(entry->content_offset); 153*23ba6841SJoseph Chen entry->content_size = switch_int(entry->content_size); 154*23ba6841SJoseph Chen } 155*23ba6841SJoseph Chen 156*23ba6841SJoseph Chen static int inline get_ptn_offset(void) 157*23ba6841SJoseph Chen { 158*23ba6841SJoseph Chen return 0; 159*23ba6841SJoseph Chen } 160*23ba6841SJoseph Chen 161*23ba6841SJoseph Chen static bool StorageWriteLba(int offset_block, void *data, int blocks) 162*23ba6841SJoseph Chen { 163*23ba6841SJoseph Chen bool ret = false; 164*23ba6841SJoseph Chen FILE *file = fopen(image_path, "rb+"); 165*23ba6841SJoseph Chen if (!file) 166*23ba6841SJoseph Chen goto end; 167*23ba6841SJoseph Chen int offset = offset_block * BLOCK_SIZE; 168*23ba6841SJoseph Chen fseek(file, offset, SEEK_SET); 169*23ba6841SJoseph Chen if (offset != ftell(file)) { 170*23ba6841SJoseph Chen LOGE("Failed to seek %s to %d!", image_path, offset); 171*23ba6841SJoseph Chen goto end; 172*23ba6841SJoseph Chen } 173*23ba6841SJoseph Chen if (!fwrite(data, blocks * BLOCK_SIZE, 1, file)) { 174*23ba6841SJoseph Chen LOGE("Failed to write %s!", image_path); 175*23ba6841SJoseph Chen goto end; 176*23ba6841SJoseph Chen } 177*23ba6841SJoseph Chen ret = true; 178*23ba6841SJoseph Chen end: 179*23ba6841SJoseph Chen if (file) 180*23ba6841SJoseph Chen fclose(file); 181*23ba6841SJoseph Chen return ret; 182*23ba6841SJoseph Chen } 183*23ba6841SJoseph Chen 184*23ba6841SJoseph Chen static bool StorageReadLba(int offset_block, void *data, int blocks) 185*23ba6841SJoseph Chen { 186*23ba6841SJoseph Chen bool ret = false; 187*23ba6841SJoseph Chen FILE *file = fopen(image_path, "rb"); 188*23ba6841SJoseph Chen if (!file) 189*23ba6841SJoseph Chen goto end; 190*23ba6841SJoseph Chen int offset = offset_block * BLOCK_SIZE; 191*23ba6841SJoseph Chen fseek(file, offset, SEEK_SET); 192*23ba6841SJoseph Chen if (offset != ftell(file)) { 193*23ba6841SJoseph Chen goto end; 194*23ba6841SJoseph Chen } 195*23ba6841SJoseph Chen if (!fread(data, blocks * BLOCK_SIZE, 1, file)) { 196*23ba6841SJoseph Chen goto end; 197*23ba6841SJoseph Chen } 198*23ba6841SJoseph Chen ret = true; 199*23ba6841SJoseph Chen end: 200*23ba6841SJoseph Chen if (file) 201*23ba6841SJoseph Chen fclose(file); 202*23ba6841SJoseph Chen return ret; 203*23ba6841SJoseph Chen } 204*23ba6841SJoseph Chen 205*23ba6841SJoseph Chen static bool write_data(int offset_block, void *data, size_t len) 206*23ba6841SJoseph Chen { 207*23ba6841SJoseph Chen bool ret = false; 208*23ba6841SJoseph Chen if (!data) 209*23ba6841SJoseph Chen goto end; 210*23ba6841SJoseph Chen int blocks = len / BLOCK_SIZE; 211*23ba6841SJoseph Chen if (blocks && !StorageWriteLba(offset_block, data, blocks)) { 212*23ba6841SJoseph Chen goto end; 213*23ba6841SJoseph Chen } 214*23ba6841SJoseph Chen int left = len % BLOCK_SIZE; 215*23ba6841SJoseph Chen if (left) { 216*23ba6841SJoseph Chen char buf[BLOCK_SIZE] = "\0"; 217*23ba6841SJoseph Chen memcpy(buf, data + blocks * BLOCK_SIZE, left); 218*23ba6841SJoseph Chen if (!StorageWriteLba(offset_block + blocks, buf, 1)) 219*23ba6841SJoseph Chen goto end; 220*23ba6841SJoseph Chen } 221*23ba6841SJoseph Chen ret = true; 222*23ba6841SJoseph Chen end: 223*23ba6841SJoseph Chen return ret; 224*23ba6841SJoseph Chen } 225*23ba6841SJoseph Chen 226*23ba6841SJoseph Chen /**********************load test************************/ 227*23ba6841SJoseph Chen static int load_file(const char *file_path, int offset_block, int blocks); 228*23ba6841SJoseph Chen 229*23ba6841SJoseph Chen static int test_load(int argc, char **argv) 230*23ba6841SJoseph Chen { 231*23ba6841SJoseph Chen if (argc < 1) { 232*23ba6841SJoseph Chen LOGE("Nothing to load!"); 233*23ba6841SJoseph Chen return -1; 234*23ba6841SJoseph Chen } 235*23ba6841SJoseph Chen const char *file_path; 236*23ba6841SJoseph Chen int offset_block = 0; 237*23ba6841SJoseph Chen int blocks = 0; 238*23ba6841SJoseph Chen if (argc > 0) { 239*23ba6841SJoseph Chen file_path = (const char *)fix_path(argv[0]); 240*23ba6841SJoseph Chen argc--, argv++; 241*23ba6841SJoseph Chen } 242*23ba6841SJoseph Chen if (argc > 0) { 243*23ba6841SJoseph Chen offset_block = atoi(argv[0]); 244*23ba6841SJoseph Chen argc--, argv++; 245*23ba6841SJoseph Chen } 246*23ba6841SJoseph Chen if (argc > 0) { 247*23ba6841SJoseph Chen blocks = atoi(argv[0]); 248*23ba6841SJoseph Chen } 249*23ba6841SJoseph Chen return load_file(file_path, offset_block, blocks); 250*23ba6841SJoseph Chen } 251*23ba6841SJoseph Chen 252*23ba6841SJoseph Chen static void free_content(resource_content *content) 253*23ba6841SJoseph Chen { 254*23ba6841SJoseph Chen if (content->load_addr) { 255*23ba6841SJoseph Chen free(content->load_addr); 256*23ba6841SJoseph Chen content->load_addr = 0; 257*23ba6841SJoseph Chen } 258*23ba6841SJoseph Chen } 259*23ba6841SJoseph Chen 260*23ba6841SJoseph Chen static void tests_dump_file(const char *path, void *data, int len) 261*23ba6841SJoseph Chen { 262*23ba6841SJoseph Chen FILE *file = fopen(path, "wb"); 263*23ba6841SJoseph Chen if (!file) 264*23ba6841SJoseph Chen return; 265*23ba6841SJoseph Chen fwrite(data, len, 1, file); 266*23ba6841SJoseph Chen fclose(file); 267*23ba6841SJoseph Chen } 268*23ba6841SJoseph Chen 269*23ba6841SJoseph Chen static bool load_content(resource_content *content) 270*23ba6841SJoseph Chen { 271*23ba6841SJoseph Chen if (content->load_addr) 272*23ba6841SJoseph Chen return true; 273*23ba6841SJoseph Chen int blocks = fix_blocks(content->content_size); 274*23ba6841SJoseph Chen content->load_addr = malloc(blocks * BLOCK_SIZE); 275*23ba6841SJoseph Chen if (!content->load_addr) 276*23ba6841SJoseph Chen return false; 277*23ba6841SJoseph Chen if (!StorageReadLba(get_ptn_offset() + content->content_offset, 278*23ba6841SJoseph Chen content->load_addr, blocks)) { 279*23ba6841SJoseph Chen free_content(content); 280*23ba6841SJoseph Chen return false; 281*23ba6841SJoseph Chen } 282*23ba6841SJoseph Chen 283*23ba6841SJoseph Chen tests_dump_file(content->path, content->load_addr, content->content_size); 284*23ba6841SJoseph Chen return true; 285*23ba6841SJoseph Chen } 286*23ba6841SJoseph Chen 287*23ba6841SJoseph Chen static bool load_content_data(resource_content *content, int offset_block, 288*23ba6841SJoseph Chen void *data, int blocks) 289*23ba6841SJoseph Chen { 290*23ba6841SJoseph Chen if (!StorageReadLba(get_ptn_offset() + content->content_offset + offset_block, 291*23ba6841SJoseph Chen data, blocks)) { 292*23ba6841SJoseph Chen return false; 293*23ba6841SJoseph Chen } 294*23ba6841SJoseph Chen tests_dump_file(content->path, data, blocks * BLOCK_SIZE); 295*23ba6841SJoseph Chen return true; 296*23ba6841SJoseph Chen } 297*23ba6841SJoseph Chen 298*23ba6841SJoseph Chen static bool get_entry(const char *file_path, index_tbl_entry *entry) 299*23ba6841SJoseph Chen { 300*23ba6841SJoseph Chen bool ret = false; 301*23ba6841SJoseph Chen char buf[BLOCK_SIZE]; 302*23ba6841SJoseph Chen resource_ptn_header header; 303*23ba6841SJoseph Chen if (!StorageReadLba(get_ptn_offset(), buf, 1)) { 304*23ba6841SJoseph Chen LOGE("Failed to read header!"); 305*23ba6841SJoseph Chen goto end; 306*23ba6841SJoseph Chen } 307*23ba6841SJoseph Chen memcpy(&header, buf, sizeof(header)); 308*23ba6841SJoseph Chen 309*23ba6841SJoseph Chen if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) { 310*23ba6841SJoseph Chen LOGE("Not a resource image(%s)!", image_path); 311*23ba6841SJoseph Chen goto end; 312*23ba6841SJoseph Chen } 313*23ba6841SJoseph Chen /* test on pc, switch for be. */ 314*23ba6841SJoseph Chen fix_header(&header); 315*23ba6841SJoseph Chen 316*23ba6841SJoseph Chen /* TODO: support header_size & tbl_entry_size */ 317*23ba6841SJoseph Chen if (header.resource_ptn_version != RESOURCE_PTN_VERSION || 318*23ba6841SJoseph Chen header.header_size != RESOURCE_PTN_HDR_SIZE || 319*23ba6841SJoseph Chen header.index_tbl_version != INDEX_TBL_VERSION || 320*23ba6841SJoseph Chen header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) { 321*23ba6841SJoseph Chen LOGE("Not supported in this version!"); 322*23ba6841SJoseph Chen goto end; 323*23ba6841SJoseph Chen } 324*23ba6841SJoseph Chen 325*23ba6841SJoseph Chen int i; 326*23ba6841SJoseph Chen for (i = 0; i < header.tbl_entry_num; i++) { 327*23ba6841SJoseph Chen /* TODO: support tbl_entry_size */ 328*23ba6841SJoseph Chen if (!StorageReadLba( 329*23ba6841SJoseph Chen get_ptn_offset() + header.header_size + i * header.tbl_entry_size, 330*23ba6841SJoseph Chen buf, 1)) { 331*23ba6841SJoseph Chen LOGE("Failed to read index entry:%d!", i); 332*23ba6841SJoseph Chen goto end; 333*23ba6841SJoseph Chen } 334*23ba6841SJoseph Chen memcpy(entry, buf, sizeof(*entry)); 335*23ba6841SJoseph Chen 336*23ba6841SJoseph Chen if (memcmp(entry->tag, INDEX_TBL_ENTR_TAG, sizeof(entry->tag))) { 337*23ba6841SJoseph Chen LOGE("Something wrong with index entry:%d!", i); 338*23ba6841SJoseph Chen goto end; 339*23ba6841SJoseph Chen } 340*23ba6841SJoseph Chen 341*23ba6841SJoseph Chen if (!strncmp(entry->path, file_path, sizeof(entry->path))) 342*23ba6841SJoseph Chen break; 343*23ba6841SJoseph Chen } 344*23ba6841SJoseph Chen if (i == header.tbl_entry_num) { 345*23ba6841SJoseph Chen LOGE("Cannot find %s!", file_path); 346*23ba6841SJoseph Chen goto end; 347*23ba6841SJoseph Chen } 348*23ba6841SJoseph Chen /* test on pc, switch for be. */ 349*23ba6841SJoseph Chen fix_entry(entry); 350*23ba6841SJoseph Chen 351*23ba6841SJoseph Chen printf("Found entry:\n\tpath:%s\n\toffset:%d\tsize:%d\n", entry->path, 352*23ba6841SJoseph Chen entry->content_offset, entry->content_size); 353*23ba6841SJoseph Chen 354*23ba6841SJoseph Chen ret = true; 355*23ba6841SJoseph Chen end: 356*23ba6841SJoseph Chen return ret; 357*23ba6841SJoseph Chen } 358*23ba6841SJoseph Chen 359*23ba6841SJoseph Chen static bool get_content(resource_content *content) 360*23ba6841SJoseph Chen { 361*23ba6841SJoseph Chen bool ret = false; 362*23ba6841SJoseph Chen index_tbl_entry entry; 363*23ba6841SJoseph Chen if (!get_entry(content->path, &entry)) 364*23ba6841SJoseph Chen goto end; 365*23ba6841SJoseph Chen content->content_offset = entry.content_offset; 366*23ba6841SJoseph Chen content->content_size = entry.content_size; 367*23ba6841SJoseph Chen ret = true; 368*23ba6841SJoseph Chen end: 369*23ba6841SJoseph Chen return ret; 370*23ba6841SJoseph Chen } 371*23ba6841SJoseph Chen 372*23ba6841SJoseph Chen static int load_file(const char *file_path, int offset_block, int blocks) 373*23ba6841SJoseph Chen { 374*23ba6841SJoseph Chen printf("Try to load:%s", file_path); 375*23ba6841SJoseph Chen if (blocks) { 376*23ba6841SJoseph Chen printf(", offset block:%d, blocks:%d\n", offset_block, blocks); 377*23ba6841SJoseph Chen } else { 378*23ba6841SJoseph Chen printf("\n"); 379*23ba6841SJoseph Chen } 380*23ba6841SJoseph Chen bool ret = false; 381*23ba6841SJoseph Chen resource_content content; 382*23ba6841SJoseph Chen snprintf(content.path, sizeof(content.path), "%s", file_path); 383*23ba6841SJoseph Chen content.load_addr = 0; 384*23ba6841SJoseph Chen if (!get_content(&content)) { 385*23ba6841SJoseph Chen goto end; 386*23ba6841SJoseph Chen } 387*23ba6841SJoseph Chen if (!blocks) { 388*23ba6841SJoseph Chen if (!load_content(&content)) { 389*23ba6841SJoseph Chen goto end; 390*23ba6841SJoseph Chen } 391*23ba6841SJoseph Chen } else { 392*23ba6841SJoseph Chen void *data = malloc(blocks * BLOCK_SIZE); 393*23ba6841SJoseph Chen if (!data) 394*23ba6841SJoseph Chen goto end; 395*23ba6841SJoseph Chen if (!load_content_data(&content, offset_block, data, blocks)) { 396*23ba6841SJoseph Chen goto end; 397*23ba6841SJoseph Chen } 398*23ba6841SJoseph Chen } 399*23ba6841SJoseph Chen ret = true; 400*23ba6841SJoseph Chen end: 401*23ba6841SJoseph Chen free_content(&content); 402*23ba6841SJoseph Chen return ret; 403*23ba6841SJoseph Chen } 404*23ba6841SJoseph Chen 405*23ba6841SJoseph Chen /**********************load test end************************/ 406*23ba6841SJoseph Chen /**********************anim test************************/ 407*23ba6841SJoseph Chen 408*23ba6841SJoseph Chen static bool parse_level_conf(const char *arg, anim_level_conf *level_conf) 409*23ba6841SJoseph Chen { 410*23ba6841SJoseph Chen memset(level_conf, 0, sizeof(anim_level_conf)); 411*23ba6841SJoseph Chen char *buf = NULL; 412*23ba6841SJoseph Chen buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_CONF); 413*23ba6841SJoseph Chen if (buf) { 414*23ba6841SJoseph Chen level_conf->max_level = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_CONF)); 415*23ba6841SJoseph Chen } else { 416*23ba6841SJoseph Chen LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_CONF); 417*23ba6841SJoseph Chen return false; 418*23ba6841SJoseph Chen } 419*23ba6841SJoseph Chen buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_NUM); 420*23ba6841SJoseph Chen if (buf) { 421*23ba6841SJoseph Chen level_conf->num = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_NUM)); 422*23ba6841SJoseph Chen if (level_conf->num <= 0) { 423*23ba6841SJoseph Chen return false; 424*23ba6841SJoseph Chen } 425*23ba6841SJoseph Chen } else { 426*23ba6841SJoseph Chen LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_NUM); 427*23ba6841SJoseph Chen return false; 428*23ba6841SJoseph Chen } 429*23ba6841SJoseph Chen buf = strstr(arg, OPT_CHARGE_ANIM_DELAY); 430*23ba6841SJoseph Chen if (buf) { 431*23ba6841SJoseph Chen level_conf->delay = atoi(buf + strlen(OPT_CHARGE_ANIM_DELAY)); 432*23ba6841SJoseph Chen } 433*23ba6841SJoseph Chen buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_PFX); 434*23ba6841SJoseph Chen if (buf) { 435*23ba6841SJoseph Chen snprintf(level_conf->prefix, sizeof(level_conf->prefix), "%s", 436*23ba6841SJoseph Chen buf + strlen(OPT_CHARGE_ANIM_LEVEL_PFX)); 437*23ba6841SJoseph Chen } else { 438*23ba6841SJoseph Chen LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_PFX); 439*23ba6841SJoseph Chen return false; 440*23ba6841SJoseph Chen } 441*23ba6841SJoseph Chen 442*23ba6841SJoseph Chen LOGD("Found conf:\nmax_level:%d, num:%d, delay:%d, prefix:%s", 443*23ba6841SJoseph Chen level_conf->max_level, level_conf->num, level_conf->delay, 444*23ba6841SJoseph Chen level_conf->prefix); 445*23ba6841SJoseph Chen return true; 446*23ba6841SJoseph Chen } 447*23ba6841SJoseph Chen 448*23ba6841SJoseph Chen static int test_charge(int argc, char **argv) 449*23ba6841SJoseph Chen { 450*23ba6841SJoseph Chen const char *desc; 451*23ba6841SJoseph Chen if (argc > 0) { 452*23ba6841SJoseph Chen desc = argv[0]; 453*23ba6841SJoseph Chen } else { 454*23ba6841SJoseph Chen desc = DEF_CHARGE_DESC_PATH; 455*23ba6841SJoseph Chen } 456*23ba6841SJoseph Chen 457*23ba6841SJoseph Chen resource_content content; 458*23ba6841SJoseph Chen snprintf(content.path, sizeof(content.path), "%s", desc); 459*23ba6841SJoseph Chen content.load_addr = 0; 460*23ba6841SJoseph Chen if (!get_content(&content)) { 461*23ba6841SJoseph Chen goto end; 462*23ba6841SJoseph Chen } 463*23ba6841SJoseph Chen if (!load_content(&content)) { 464*23ba6841SJoseph Chen goto end; 465*23ba6841SJoseph Chen } 466*23ba6841SJoseph Chen 467*23ba6841SJoseph Chen char *buf = (char *)content.load_addr; 468*23ba6841SJoseph Chen char *end = buf + content.content_size - 1; 469*23ba6841SJoseph Chen *end = '\0'; 470*23ba6841SJoseph Chen LOGD("desc:\n%s", buf); 471*23ba6841SJoseph Chen 472*23ba6841SJoseph Chen int pos = 0; 473*23ba6841SJoseph Chen while (1) { 474*23ba6841SJoseph Chen char *line = (char *)memchr(buf + pos, '\n', strlen(buf + pos)); 475*23ba6841SJoseph Chen if (!line) 476*23ba6841SJoseph Chen break; 477*23ba6841SJoseph Chen *line = '\0'; 478*23ba6841SJoseph Chen LOGD("splite:%s", buf + pos); 479*23ba6841SJoseph Chen pos += (strlen(buf + pos) + 1); 480*23ba6841SJoseph Chen } 481*23ba6841SJoseph Chen 482*23ba6841SJoseph Chen int delay = 900; 483*23ba6841SJoseph Chen int only_current_level = false; 484*23ba6841SJoseph Chen anim_level_conf *level_confs = NULL; 485*23ba6841SJoseph Chen int level_conf_pos = 0; 486*23ba6841SJoseph Chen int level_conf_num = 0; 487*23ba6841SJoseph Chen 488*23ba6841SJoseph Chen while (true) { 489*23ba6841SJoseph Chen if (buf >= end) 490*23ba6841SJoseph Chen break; 491*23ba6841SJoseph Chen const char *arg = buf; 492*23ba6841SJoseph Chen buf += (strlen(buf) + 1); 493*23ba6841SJoseph Chen 494*23ba6841SJoseph Chen LOGD("parse arg:%s", arg); 495*23ba6841SJoseph Chen if (!memcmp(arg, OPT_CHARGE_ANIM_LEVEL_CONF, 496*23ba6841SJoseph Chen strlen(OPT_CHARGE_ANIM_LEVEL_CONF))) { 497*23ba6841SJoseph Chen if (!level_confs) { 498*23ba6841SJoseph Chen LOGE("Found level conf before levels!"); 499*23ba6841SJoseph Chen goto end; 500*23ba6841SJoseph Chen } 501*23ba6841SJoseph Chen if (level_conf_pos >= level_conf_num) { 502*23ba6841SJoseph Chen LOGE("Too many level confs!(%d >= %d)", level_conf_pos, level_conf_num); 503*23ba6841SJoseph Chen goto end; 504*23ba6841SJoseph Chen } 505*23ba6841SJoseph Chen if (!parse_level_conf(arg, level_confs + level_conf_pos)) { 506*23ba6841SJoseph Chen LOGE("Failed to parse level conf:%s", arg); 507*23ba6841SJoseph Chen goto end; 508*23ba6841SJoseph Chen } 509*23ba6841SJoseph Chen level_conf_pos++; 510*23ba6841SJoseph Chen } else if (!memcmp(arg, OPT_CHARGE_ANIM_DELAY, 511*23ba6841SJoseph Chen strlen(OPT_CHARGE_ANIM_DELAY))) { 512*23ba6841SJoseph Chen delay = atoi(arg + strlen(OPT_CHARGE_ANIM_DELAY)); 513*23ba6841SJoseph Chen LOGD("Found delay:%d", delay); 514*23ba6841SJoseph Chen } else if (!memcmp(arg, OPT_CHARGE_ANIM_LOOP_CUR, 515*23ba6841SJoseph Chen strlen(OPT_CHARGE_ANIM_LOOP_CUR))) { 516*23ba6841SJoseph Chen only_current_level = 517*23ba6841SJoseph Chen !memcmp(arg + strlen(OPT_CHARGE_ANIM_LOOP_CUR), "true", 4); 518*23ba6841SJoseph Chen LOGD("Found only_current_level:%d", only_current_level); 519*23ba6841SJoseph Chen } else if (!memcmp(arg, OPT_CHARGE_ANIM_LEVELS, 520*23ba6841SJoseph Chen strlen(OPT_CHARGE_ANIM_LEVELS))) { 521*23ba6841SJoseph Chen if (level_conf_num) { 522*23ba6841SJoseph Chen goto end; 523*23ba6841SJoseph Chen } 524*23ba6841SJoseph Chen level_conf_num = atoi(arg + strlen(OPT_CHARGE_ANIM_LEVELS)); 525*23ba6841SJoseph Chen if (!level_conf_num) { 526*23ba6841SJoseph Chen goto end; 527*23ba6841SJoseph Chen } 528*23ba6841SJoseph Chen level_confs = 529*23ba6841SJoseph Chen (anim_level_conf *)malloc(level_conf_num * sizeof(anim_level_conf)); 530*23ba6841SJoseph Chen LOGD("Found levels:%d", level_conf_num); 531*23ba6841SJoseph Chen } else { 532*23ba6841SJoseph Chen LOGE("Unknown arg:%s", arg); 533*23ba6841SJoseph Chen goto end; 534*23ba6841SJoseph Chen } 535*23ba6841SJoseph Chen } 536*23ba6841SJoseph Chen 537*23ba6841SJoseph Chen if (level_conf_pos != level_conf_num || !level_conf_num) { 538*23ba6841SJoseph Chen LOGE("Something wrong with level confs!"); 539*23ba6841SJoseph Chen goto end; 540*23ba6841SJoseph Chen } 541*23ba6841SJoseph Chen 542*23ba6841SJoseph Chen int i = 0, j = 0; 543*23ba6841SJoseph Chen for (i = 0; i < level_conf_num; i++) { 544*23ba6841SJoseph Chen if (!level_confs[i].delay) { 545*23ba6841SJoseph Chen level_confs[i].delay = delay; 546*23ba6841SJoseph Chen } 547*23ba6841SJoseph Chen if (!level_confs[i].delay) { 548*23ba6841SJoseph Chen LOGE("Missing delay in level conf:%d", i); 549*23ba6841SJoseph Chen goto end; 550*23ba6841SJoseph Chen } 551*23ba6841SJoseph Chen for (j = 0; j < i; j++) { 552*23ba6841SJoseph Chen if (level_confs[j].max_level == level_confs[i].max_level) { 553*23ba6841SJoseph Chen LOGE("Dup level conf:%d", i); 554*23ba6841SJoseph Chen goto end; 555*23ba6841SJoseph Chen } 556*23ba6841SJoseph Chen if (level_confs[j].max_level > level_confs[i].max_level) { 557*23ba6841SJoseph Chen anim_level_conf conf = level_confs[i]; 558*23ba6841SJoseph Chen memmove(level_confs + j + 1, level_confs + j, 559*23ba6841SJoseph Chen (i - j) * sizeof(anim_level_conf)); 560*23ba6841SJoseph Chen level_confs[j] = conf; 561*23ba6841SJoseph Chen } 562*23ba6841SJoseph Chen } 563*23ba6841SJoseph Chen } 564*23ba6841SJoseph Chen 565*23ba6841SJoseph Chen printf("Parse anim desc(%s):\n", desc); 566*23ba6841SJoseph Chen printf("only_current_level=%d\n", only_current_level); 567*23ba6841SJoseph Chen printf("level conf:\n"); 568*23ba6841SJoseph Chen for (i = 0; i < level_conf_num; i++) { 569*23ba6841SJoseph Chen printf("\tmax=%d, delay=%d, num=%d, prefix=%s\n", level_confs[i].max_level, 570*23ba6841SJoseph Chen level_confs[i].delay, level_confs[i].num, level_confs[i].prefix); 571*23ba6841SJoseph Chen } 572*23ba6841SJoseph Chen 573*23ba6841SJoseph Chen end: 574*23ba6841SJoseph Chen free_content(&content); 575*23ba6841SJoseph Chen return 0; 576*23ba6841SJoseph Chen } 577*23ba6841SJoseph Chen 578*23ba6841SJoseph Chen /**********************anim test end************************/ 579*23ba6841SJoseph Chen /**********************append file************************/ 580*23ba6841SJoseph Chen 581*23ba6841SJoseph Chen static const char *PROG = NULL; 582*23ba6841SJoseph Chen static resource_ptn_header header; 583*23ba6841SJoseph Chen static bool just_print = false; 584*23ba6841SJoseph Chen static char root_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0"; 585*23ba6841SJoseph Chen 586*23ba6841SJoseph Chen static void version(void) 587*23ba6841SJoseph Chen { 588*23ba6841SJoseph Chen printf("%s (cjf@rock-chips.com)\t" VERSION "\n", PROG); 589*23ba6841SJoseph Chen } 590*23ba6841SJoseph Chen 591*23ba6841SJoseph Chen static void usage(void) 592*23ba6841SJoseph Chen { 593*23ba6841SJoseph Chen printf("Usage: %s [options] [FILES]\n", PROG); 594*23ba6841SJoseph Chen printf("Tools for Rockchip's resource image.\n"); 595*23ba6841SJoseph Chen version(); 596*23ba6841SJoseph Chen printf("Options:\n"); 597*23ba6841SJoseph Chen printf("\t" OPT_PACK "\t\t\tPack image from given files.\n"); 598*23ba6841SJoseph Chen printf("\t" OPT_UNPACK "\t\tUnpack given image to current dir.\n"); 599*23ba6841SJoseph Chen printf("\t" OPT_IMAGE "path" 600*23ba6841SJoseph Chen "\t\tSpecify input/output image path.\n"); 601*23ba6841SJoseph Chen printf("\t" OPT_PRINT "\t\t\tJust print informations.\n"); 602*23ba6841SJoseph Chen printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n"); 603*23ba6841SJoseph Chen printf("\t" OPT_HELP "\t\t\tDisplay this information.\n"); 604*23ba6841SJoseph Chen printf("\t" OPT_VERSION "\t\tDisplay version information.\n"); 605*23ba6841SJoseph Chen printf("\t" OPT_ROOT "path" 606*23ba6841SJoseph Chen "\t\tSpecify resources' root dir.\n"); 607*23ba6841SJoseph Chen } 608*23ba6841SJoseph Chen 609*23ba6841SJoseph Chen static int pack_image(int file_num, const char **files); 610*23ba6841SJoseph Chen static int unpack_image(const char *unpack_dir); 611*23ba6841SJoseph Chen 612*23ba6841SJoseph Chen enum ACTION { 613*23ba6841SJoseph Chen ACTION_PACK, 614*23ba6841SJoseph Chen ACTION_UNPACK, 615*23ba6841SJoseph Chen ACTION_TEST_LOAD, 616*23ba6841SJoseph Chen ACTION_TEST_CHARGE, 617*23ba6841SJoseph Chen }; 618*23ba6841SJoseph Chen 619*23ba6841SJoseph Chen int main(int argc, char **argv) 620*23ba6841SJoseph Chen { 621*23ba6841SJoseph Chen PROG = fix_path(argv[0]); 622*23ba6841SJoseph Chen 623*23ba6841SJoseph Chen enum ACTION action = ACTION_PACK; 624*23ba6841SJoseph Chen 625*23ba6841SJoseph Chen argc--, argv++; 626*23ba6841SJoseph Chen while (argc > 0 && argv[0][0] == '-') { 627*23ba6841SJoseph Chen /* it's a opt arg. */ 628*23ba6841SJoseph Chen const char *arg = argv[0]; 629*23ba6841SJoseph Chen argc--, argv++; 630*23ba6841SJoseph Chen if (!strcmp(OPT_VERBOSE, arg)) { 631*23ba6841SJoseph Chen g_debug = true; 632*23ba6841SJoseph Chen } else if (!strcmp(OPT_HELP, arg)) { 633*23ba6841SJoseph Chen usage(); 634*23ba6841SJoseph Chen return 0; 635*23ba6841SJoseph Chen } else if (!strcmp(OPT_VERSION, arg)) { 636*23ba6841SJoseph Chen version(); 637*23ba6841SJoseph Chen return 0; 638*23ba6841SJoseph Chen } else if (!strcmp(OPT_PRINT, arg)) { 639*23ba6841SJoseph Chen just_print = true; 640*23ba6841SJoseph Chen } else if (!strcmp(OPT_PACK, arg)) { 641*23ba6841SJoseph Chen action = ACTION_PACK; 642*23ba6841SJoseph Chen } else if (!strcmp(OPT_UNPACK, arg)) { 643*23ba6841SJoseph Chen action = ACTION_UNPACK; 644*23ba6841SJoseph Chen } else if (!strcmp(OPT_TEST_LOAD, arg)) { 645*23ba6841SJoseph Chen action = ACTION_TEST_LOAD; 646*23ba6841SJoseph Chen } else if (!strcmp(OPT_TEST_CHARGE, arg)) { 647*23ba6841SJoseph Chen action = ACTION_TEST_CHARGE; 648*23ba6841SJoseph Chen } else if (!memcmp(OPT_IMAGE, arg, strlen(OPT_IMAGE))) { 649*23ba6841SJoseph Chen snprintf(image_path, sizeof(image_path), "%s", arg + strlen(OPT_IMAGE)); 650*23ba6841SJoseph Chen } else if (!memcmp(OPT_ROOT, arg, strlen(OPT_ROOT))) { 651*23ba6841SJoseph Chen snprintf(root_path, sizeof(root_path), "%s", arg + strlen(OPT_ROOT)); 652*23ba6841SJoseph Chen } else { 653*23ba6841SJoseph Chen LOGE("Unknown opt:%s", arg); 654*23ba6841SJoseph Chen usage(); 655*23ba6841SJoseph Chen return -1; 656*23ba6841SJoseph Chen } 657*23ba6841SJoseph Chen } 658*23ba6841SJoseph Chen 659*23ba6841SJoseph Chen if (!image_path[0]) { 660*23ba6841SJoseph Chen snprintf(image_path, sizeof(image_path), "%s", DEFAULT_IMAGE_PATH); 661*23ba6841SJoseph Chen } 662*23ba6841SJoseph Chen 663*23ba6841SJoseph Chen switch (action) { 664*23ba6841SJoseph Chen case ACTION_PACK: { 665*23ba6841SJoseph Chen int file_num = argc; 666*23ba6841SJoseph Chen const char **files = (const char **)argv; 667*23ba6841SJoseph Chen if (!file_num) { 668*23ba6841SJoseph Chen LOGE("No file to pack!"); 669*23ba6841SJoseph Chen return 0; 670*23ba6841SJoseph Chen } 671*23ba6841SJoseph Chen LOGD("try to pack %d files.", file_num); 672*23ba6841SJoseph Chen return pack_image(file_num, files); 673*23ba6841SJoseph Chen } 674*23ba6841SJoseph Chen case ACTION_UNPACK: { 675*23ba6841SJoseph Chen return unpack_image(argc > 0 ? argv[0] : DEFAULT_UNPACK_DIR); 676*23ba6841SJoseph Chen } 677*23ba6841SJoseph Chen case ACTION_TEST_LOAD: { 678*23ba6841SJoseph Chen return test_load(argc, argv); 679*23ba6841SJoseph Chen } 680*23ba6841SJoseph Chen case ACTION_TEST_CHARGE: { 681*23ba6841SJoseph Chen return test_charge(argc, argv); 682*23ba6841SJoseph Chen } 683*23ba6841SJoseph Chen } 684*23ba6841SJoseph Chen /* not reach here. */ 685*23ba6841SJoseph Chen return -1; 686*23ba6841SJoseph Chen } 687*23ba6841SJoseph Chen 688*23ba6841SJoseph Chen /************unpack code****************/ 689*23ba6841SJoseph Chen static bool mkdirs(char *path) 690*23ba6841SJoseph Chen { 691*23ba6841SJoseph Chen char *tmp = path; 692*23ba6841SJoseph Chen char *pos = NULL; 693*23ba6841SJoseph Chen char buf[MAX_INDEX_ENTRY_PATH_LEN]; 694*23ba6841SJoseph Chen bool ret = true; 695*23ba6841SJoseph Chen while ((pos = memchr(tmp, '/', strlen(tmp)))) { 696*23ba6841SJoseph Chen strcpy(buf, path); 697*23ba6841SJoseph Chen buf[pos - path] = '\0'; 698*23ba6841SJoseph Chen tmp = pos + 1; 699*23ba6841SJoseph Chen LOGD("mkdir:%s", buf); 700*23ba6841SJoseph Chen if (!mkdir(buf, 0755)) { 701*23ba6841SJoseph Chen ret = false; 702*23ba6841SJoseph Chen } 703*23ba6841SJoseph Chen } 704*23ba6841SJoseph Chen if (!ret) 705*23ba6841SJoseph Chen LOGD("Failed to mkdir(%s)!", path); 706*23ba6841SJoseph Chen return ret; 707*23ba6841SJoseph Chen } 708*23ba6841SJoseph Chen 709*23ba6841SJoseph Chen static bool dump_file(FILE *file, const char *unpack_dir, 710*23ba6841SJoseph Chen index_tbl_entry entry) 711*23ba6841SJoseph Chen { 712*23ba6841SJoseph Chen LOGD("try to dump entry:%s", entry.path); 713*23ba6841SJoseph Chen bool ret = false; 714*23ba6841SJoseph Chen FILE *out_file = NULL; 715*23ba6841SJoseph Chen long int pos = 0; 716*23ba6841SJoseph Chen char path[MAX_INDEX_ENTRY_PATH_LEN * 2 + 1]; 717*23ba6841SJoseph Chen if (just_print) { 718*23ba6841SJoseph Chen ret = true; 719*23ba6841SJoseph Chen goto done; 720*23ba6841SJoseph Chen } 721*23ba6841SJoseph Chen 722*23ba6841SJoseph Chen pos = ftell(file); 723*23ba6841SJoseph Chen snprintf(path, sizeof(path), "%s/%s", unpack_dir, entry.path); 724*23ba6841SJoseph Chen mkdirs(path); 725*23ba6841SJoseph Chen out_file = fopen(path, "wb"); 726*23ba6841SJoseph Chen if (!out_file) { 727*23ba6841SJoseph Chen LOGE("Failed to create:%s", path); 728*23ba6841SJoseph Chen goto end; 729*23ba6841SJoseph Chen } 730*23ba6841SJoseph Chen long int offset = entry.content_offset * BLOCK_SIZE; 731*23ba6841SJoseph Chen fseek(file, offset, SEEK_SET); 732*23ba6841SJoseph Chen if (offset != ftell(file)) { 733*23ba6841SJoseph Chen LOGE("Failed to read content:%s", entry.path); 734*23ba6841SJoseph Chen goto end; 735*23ba6841SJoseph Chen } 736*23ba6841SJoseph Chen char buf[BLOCK_SIZE]; 737*23ba6841SJoseph Chen int n; 738*23ba6841SJoseph Chen int len = entry.content_size; 739*23ba6841SJoseph Chen while (len > 0) { 740*23ba6841SJoseph Chen n = len > BLOCK_SIZE ? BLOCK_SIZE : len; 741*23ba6841SJoseph Chen if (!fread(buf, n, 1, file)) { 742*23ba6841SJoseph Chen LOGE("Failed to read content:%s", entry.path); 743*23ba6841SJoseph Chen goto end; 744*23ba6841SJoseph Chen } 745*23ba6841SJoseph Chen if (!fwrite(buf, n, 1, out_file)) { 746*23ba6841SJoseph Chen LOGE("Failed to write:%s", entry.path); 747*23ba6841SJoseph Chen goto end; 748*23ba6841SJoseph Chen } 749*23ba6841SJoseph Chen len -= n; 750*23ba6841SJoseph Chen } 751*23ba6841SJoseph Chen done: 752*23ba6841SJoseph Chen ret = true; 753*23ba6841SJoseph Chen end: 754*23ba6841SJoseph Chen if (out_file) 755*23ba6841SJoseph Chen fclose(out_file); 756*23ba6841SJoseph Chen if (pos) 757*23ba6841SJoseph Chen fseek(file, pos, SEEK_SET); 758*23ba6841SJoseph Chen return ret; 759*23ba6841SJoseph Chen } 760*23ba6841SJoseph Chen 761*23ba6841SJoseph Chen static int unpack_image(const char *dir) 762*23ba6841SJoseph Chen { 763*23ba6841SJoseph Chen FILE *image_file = NULL; 764*23ba6841SJoseph Chen bool ret = false; 765*23ba6841SJoseph Chen char unpack_dir[MAX_INDEX_ENTRY_PATH_LEN]; 766*23ba6841SJoseph Chen if (just_print) 767*23ba6841SJoseph Chen dir = "."; 768*23ba6841SJoseph Chen snprintf(unpack_dir, sizeof(unpack_dir), "%s", dir); 769*23ba6841SJoseph Chen if (!strlen(unpack_dir)) { 770*23ba6841SJoseph Chen goto end; 771*23ba6841SJoseph Chen } else if (unpack_dir[strlen(unpack_dir) - 1] == '/') { 772*23ba6841SJoseph Chen unpack_dir[strlen(unpack_dir) - 1] = '\0'; 773*23ba6841SJoseph Chen } 774*23ba6841SJoseph Chen 775*23ba6841SJoseph Chen mkdir(unpack_dir, 0755); 776*23ba6841SJoseph Chen image_file = fopen(image_path, "rb"); 777*23ba6841SJoseph Chen char buf[BLOCK_SIZE]; 778*23ba6841SJoseph Chen if (!image_file) { 779*23ba6841SJoseph Chen LOGE("Failed to open:%s", image_path); 780*23ba6841SJoseph Chen goto end; 781*23ba6841SJoseph Chen } 782*23ba6841SJoseph Chen if (!fread(buf, BLOCK_SIZE, 1, image_file)) { 783*23ba6841SJoseph Chen LOGE("Failed to read header!"); 784*23ba6841SJoseph Chen goto end; 785*23ba6841SJoseph Chen } 786*23ba6841SJoseph Chen memcpy(&header, buf, sizeof(header)); 787*23ba6841SJoseph Chen 788*23ba6841SJoseph Chen if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) { 789*23ba6841SJoseph Chen LOGE("Not a resource image(%s)!", image_path); 790*23ba6841SJoseph Chen goto end; 791*23ba6841SJoseph Chen } 792*23ba6841SJoseph Chen /* switch for be. */ 793*23ba6841SJoseph Chen fix_header(&header); 794*23ba6841SJoseph Chen 795*23ba6841SJoseph Chen printf("Dump header:\n"); 796*23ba6841SJoseph Chen printf("partition version:%d.%d\n", header.resource_ptn_version, 797*23ba6841SJoseph Chen header.index_tbl_version); 798*23ba6841SJoseph Chen printf("header size:%d\n", header.header_size); 799*23ba6841SJoseph Chen printf("index tbl:\n\toffset:%d\tentry size:%d\tentry num:%d\n", 800*23ba6841SJoseph Chen header.tbl_offset, header.tbl_entry_size, header.tbl_entry_num); 801*23ba6841SJoseph Chen 802*23ba6841SJoseph Chen /* TODO: support header_size & tbl_entry_size */ 803*23ba6841SJoseph Chen if (header.resource_ptn_version != RESOURCE_PTN_VERSION || 804*23ba6841SJoseph Chen header.header_size != RESOURCE_PTN_HDR_SIZE || 805*23ba6841SJoseph Chen header.index_tbl_version != INDEX_TBL_VERSION || 806*23ba6841SJoseph Chen header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) { 807*23ba6841SJoseph Chen LOGE("Not supported in this version!"); 808*23ba6841SJoseph Chen goto end; 809*23ba6841SJoseph Chen } 810*23ba6841SJoseph Chen 811*23ba6841SJoseph Chen printf("Dump Index table:\n"); 812*23ba6841SJoseph Chen index_tbl_entry entry; 813*23ba6841SJoseph Chen int i; 814*23ba6841SJoseph Chen for (i = 0; i < header.tbl_entry_num; i++) { 815*23ba6841SJoseph Chen /* TODO: support tbl_entry_size */ 816*23ba6841SJoseph Chen if (!fread(buf, BLOCK_SIZE, 1, image_file)) { 817*23ba6841SJoseph Chen LOGE("Failed to read index entry:%d!", i); 818*23ba6841SJoseph Chen goto end; 819*23ba6841SJoseph Chen } 820*23ba6841SJoseph Chen memcpy(&entry, buf, sizeof(entry)); 821*23ba6841SJoseph Chen 822*23ba6841SJoseph Chen if (memcmp(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag))) { 823*23ba6841SJoseph Chen LOGE("Something wrong with index entry:%d!", i); 824*23ba6841SJoseph Chen goto end; 825*23ba6841SJoseph Chen } 826*23ba6841SJoseph Chen /* switch for be. */ 827*23ba6841SJoseph Chen fix_entry(&entry); 828*23ba6841SJoseph Chen 829*23ba6841SJoseph Chen printf("entry(%d):\n\tpath:%s\n\toffset:%d\tsize:%d\n", i, entry.path, 830*23ba6841SJoseph Chen entry.content_offset, entry.content_size); 831*23ba6841SJoseph Chen if (!dump_file(image_file, unpack_dir, entry)) { 832*23ba6841SJoseph Chen goto end; 833*23ba6841SJoseph Chen } 834*23ba6841SJoseph Chen } 835*23ba6841SJoseph Chen printf("Unack %s to %s successed!\n", image_path, unpack_dir); 836*23ba6841SJoseph Chen ret = true; 837*23ba6841SJoseph Chen end: 838*23ba6841SJoseph Chen if (image_file) 839*23ba6841SJoseph Chen fclose(image_file); 840*23ba6841SJoseph Chen return ret ? 0 : -1; 841*23ba6841SJoseph Chen } 842*23ba6841SJoseph Chen 843*23ba6841SJoseph Chen /************unpack code end****************/ 844*23ba6841SJoseph Chen /************pack code****************/ 845*23ba6841SJoseph Chen 846*23ba6841SJoseph Chen static inline size_t get_file_size(const char *path) 847*23ba6841SJoseph Chen { 848*23ba6841SJoseph Chen LOGD("try to get size(%s)...", path); 849*23ba6841SJoseph Chen struct stat st; 850*23ba6841SJoseph Chen if (stat(path, &st) < 0) { 851*23ba6841SJoseph Chen LOGE("Failed to get size:%s", path); 852*23ba6841SJoseph Chen return -1; 853*23ba6841SJoseph Chen } 854*23ba6841SJoseph Chen LOGD("path:%s, size:%ld", path, st.st_size); 855*23ba6841SJoseph Chen return st.st_size; 856*23ba6841SJoseph Chen } 857*23ba6841SJoseph Chen 858*23ba6841SJoseph Chen static int write_file(int offset_block, const char *src_path) 859*23ba6841SJoseph Chen { 860*23ba6841SJoseph Chen LOGD("try to write file(%s) to offset:%d...", src_path, offset_block); 861*23ba6841SJoseph Chen char buf[BLOCK_SIZE]; 862*23ba6841SJoseph Chen int ret = -1; 863*23ba6841SJoseph Chen size_t file_size; 864*23ba6841SJoseph Chen int blocks; 865*23ba6841SJoseph Chen FILE *src_file = fopen(src_path, "rb"); 866*23ba6841SJoseph Chen if (!src_file) { 867*23ba6841SJoseph Chen LOGE("Failed to open:%s", src_path); 868*23ba6841SJoseph Chen goto end; 869*23ba6841SJoseph Chen } 870*23ba6841SJoseph Chen 871*23ba6841SJoseph Chen file_size = get_file_size(src_path); 872*23ba6841SJoseph Chen if (file_size < 0) { 873*23ba6841SJoseph Chen goto end; 874*23ba6841SJoseph Chen } 875*23ba6841SJoseph Chen blocks = fix_blocks(file_size); 876*23ba6841SJoseph Chen 877*23ba6841SJoseph Chen int i; 878*23ba6841SJoseph Chen for (i = 0; i < blocks; i++) { 879*23ba6841SJoseph Chen memset(buf, 0, sizeof(buf)); 880*23ba6841SJoseph Chen if (!fread(buf, 1, BLOCK_SIZE, src_file)) { 881*23ba6841SJoseph Chen LOGE("Failed to read:%s", src_path); 882*23ba6841SJoseph Chen goto end; 883*23ba6841SJoseph Chen } 884*23ba6841SJoseph Chen if (!write_data(offset_block + i, buf, BLOCK_SIZE)) { 885*23ba6841SJoseph Chen goto end; 886*23ba6841SJoseph Chen } 887*23ba6841SJoseph Chen } 888*23ba6841SJoseph Chen ret = blocks; 889*23ba6841SJoseph Chen end: 890*23ba6841SJoseph Chen if (src_file) 891*23ba6841SJoseph Chen fclose(src_file); 892*23ba6841SJoseph Chen return ret; 893*23ba6841SJoseph Chen } 894*23ba6841SJoseph Chen 895*23ba6841SJoseph Chen static bool write_header(const int file_num) 896*23ba6841SJoseph Chen { 897*23ba6841SJoseph Chen LOGD("try to write header..."); 898*23ba6841SJoseph Chen memcpy(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic)); 899*23ba6841SJoseph Chen header.resource_ptn_version = RESOURCE_PTN_VERSION; 900*23ba6841SJoseph Chen header.index_tbl_version = INDEX_TBL_VERSION; 901*23ba6841SJoseph Chen header.header_size = RESOURCE_PTN_HDR_SIZE; 902*23ba6841SJoseph Chen header.tbl_offset = header.header_size; 903*23ba6841SJoseph Chen header.tbl_entry_size = INDEX_TBL_ENTR_SIZE; 904*23ba6841SJoseph Chen header.tbl_entry_num = file_num; 905*23ba6841SJoseph Chen 906*23ba6841SJoseph Chen /* switch for le. */ 907*23ba6841SJoseph Chen resource_ptn_header hdr = header; 908*23ba6841SJoseph Chen fix_header(&hdr); 909*23ba6841SJoseph Chen return write_data(0, &hdr, sizeof(hdr)); 910*23ba6841SJoseph Chen } 911*23ba6841SJoseph Chen 912*23ba6841SJoseph Chen static bool write_index_tbl(const int file_num, const char **files) 913*23ba6841SJoseph Chen { 914*23ba6841SJoseph Chen LOGD("try to write index table..."); 915*23ba6841SJoseph Chen bool ret = false; 916*23ba6841SJoseph Chen bool foundFdt = false; 917*23ba6841SJoseph Chen int offset = 918*23ba6841SJoseph Chen header.header_size + header.tbl_entry_size * header.tbl_entry_num; 919*23ba6841SJoseph Chen index_tbl_entry entry; 920*23ba6841SJoseph Chen memcpy(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag)); 921*23ba6841SJoseph Chen int i; 922*23ba6841SJoseph Chen for (i = 0; i < file_num; i++) { 923*23ba6841SJoseph Chen size_t file_size = get_file_size(files[i]); 924*23ba6841SJoseph Chen if (file_size < 0) 925*23ba6841SJoseph Chen goto end; 926*23ba6841SJoseph Chen entry.content_size = file_size; 927*23ba6841SJoseph Chen entry.content_offset = offset; 928*23ba6841SJoseph Chen 929*23ba6841SJoseph Chen if (write_file(offset, files[i]) < 0) 930*23ba6841SJoseph Chen goto end; 931*23ba6841SJoseph Chen 932*23ba6841SJoseph Chen LOGD("try to write index entry(%s)...", files[i]); 933*23ba6841SJoseph Chen 934*23ba6841SJoseph Chen /* switch for le. */ 935*23ba6841SJoseph Chen fix_entry(&entry); 936*23ba6841SJoseph Chen memset(entry.path, 0, sizeof(entry.path)); 937*23ba6841SJoseph Chen const char *path = files[i]; 938*23ba6841SJoseph Chen if (root_path[0]) { 939*23ba6841SJoseph Chen if (!strncmp(path, root_path, strlen(root_path))) { 940*23ba6841SJoseph Chen path += strlen(root_path); 941*23ba6841SJoseph Chen if (path[0] == '/') 942*23ba6841SJoseph Chen path++; 943*23ba6841SJoseph Chen } 944*23ba6841SJoseph Chen } 945*23ba6841SJoseph Chen path = fix_path(path); 946*23ba6841SJoseph Chen if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) { 947*23ba6841SJoseph Chen if (!foundFdt) { 948*23ba6841SJoseph Chen /* use default path. */ 949*23ba6841SJoseph Chen LOGD("mod fdt path:%s -> %s...", files[i], FDT_PATH); 950*23ba6841SJoseph Chen path = FDT_PATH; 951*23ba6841SJoseph Chen foundFdt = true; 952*23ba6841SJoseph Chen } 953*23ba6841SJoseph Chen } 954*23ba6841SJoseph Chen snprintf(entry.path, sizeof(entry.path), "%s", path); 955*23ba6841SJoseph Chen offset += fix_blocks(file_size); 956*23ba6841SJoseph Chen if (!write_data(header.header_size + i * header.tbl_entry_size, &entry, 957*23ba6841SJoseph Chen sizeof(entry))) 958*23ba6841SJoseph Chen goto end; 959*23ba6841SJoseph Chen } 960*23ba6841SJoseph Chen ret = true; 961*23ba6841SJoseph Chen end: 962*23ba6841SJoseph Chen return ret; 963*23ba6841SJoseph Chen } 964*23ba6841SJoseph Chen 965*23ba6841SJoseph Chen static int pack_image(int file_num, const char **files) 966*23ba6841SJoseph Chen { 967*23ba6841SJoseph Chen bool ret = false; 968*23ba6841SJoseph Chen FILE *image_file = fopen(image_path, "wb"); 969*23ba6841SJoseph Chen if (!image_file) { 970*23ba6841SJoseph Chen LOGE("Failed to create:%s", image_path); 971*23ba6841SJoseph Chen goto end; 972*23ba6841SJoseph Chen } 973*23ba6841SJoseph Chen fclose(image_file); 974*23ba6841SJoseph Chen 975*23ba6841SJoseph Chen /* prepare files */ 976*23ba6841SJoseph Chen int i = 0; 977*23ba6841SJoseph Chen int pos = 0; 978*23ba6841SJoseph Chen const char *tmp; 979*23ba6841SJoseph Chen for (i = 0; i < file_num; i++) { 980*23ba6841SJoseph Chen if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) { 981*23ba6841SJoseph Chen /* dtb files for kernel. */ 982*23ba6841SJoseph Chen tmp = files[pos]; 983*23ba6841SJoseph Chen files[pos] = files[i]; 984*23ba6841SJoseph Chen files[i] = tmp; 985*23ba6841SJoseph Chen pos++; 986*23ba6841SJoseph Chen } else if (!strcmp(fix_path(image_path), fix_path(files[i]))) { 987*23ba6841SJoseph Chen /* not to pack image itself! */ 988*23ba6841SJoseph Chen tmp = files[file_num - 1]; 989*23ba6841SJoseph Chen files[file_num - 1] = files[i]; 990*23ba6841SJoseph Chen files[i] = tmp; 991*23ba6841SJoseph Chen file_num--; 992*23ba6841SJoseph Chen } 993*23ba6841SJoseph Chen } 994*23ba6841SJoseph Chen 995*23ba6841SJoseph Chen if (!write_header(file_num)) { 996*23ba6841SJoseph Chen LOGE("Failed to write header!"); 997*23ba6841SJoseph Chen goto end; 998*23ba6841SJoseph Chen } 999*23ba6841SJoseph Chen if (!write_index_tbl(file_num, files)) { 1000*23ba6841SJoseph Chen LOGE("Failed to write index table!"); 1001*23ba6841SJoseph Chen goto end; 1002*23ba6841SJoseph Chen } 1003*23ba6841SJoseph Chen printf("Pack to %s successed!\n", image_path); 1004*23ba6841SJoseph Chen ret = true; 1005*23ba6841SJoseph Chen end: 1006*23ba6841SJoseph Chen return ret ? 0 : -1; 1007*23ba6841SJoseph Chen } 1008*23ba6841SJoseph Chen 1009*23ba6841SJoseph Chen /************pack code end****************/ 1010