1*08dcd37cSAndy Yan /* 2*08dcd37cSAndy Yan * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3*08dcd37cSAndy Yan * 4*08dcd37cSAndy Yan * SPDX-License-Identifier: GPL-2.0+ 5*08dcd37cSAndy Yan */ 6*08dcd37cSAndy Yan #include <common.h> 7*08dcd37cSAndy Yan #include <malloc.h> 8*08dcd37cSAndy Yan #include <linux/list.h> 9*08dcd37cSAndy Yan #include <asm/arch/resource_img.h> 10*08dcd37cSAndy Yan #include "rockchip_parameter.h" 11*08dcd37cSAndy Yan #include "rockchip_blk.h" 12*08dcd37cSAndy Yan 13*08dcd37cSAndy Yan #define PART_RESOURCE "resource" 14*08dcd37cSAndy Yan #define RESOURCE_MAGIC "RSCE" 15*08dcd37cSAndy Yan #define RESOURCE_MAGIC_SIZE 4 16*08dcd37cSAndy Yan #define RESOURCE_VERSION 0 17*08dcd37cSAndy Yan #define CONTENT_VERSION 0 18*08dcd37cSAndy Yan #define ENTRY_TAG "ENTR" 19*08dcd37cSAndy Yan #define ENTRY_TAG_SIZE 4 20*08dcd37cSAndy Yan #define MAX_FILE_NAME_LEN 256 21*08dcd37cSAndy Yan 22*08dcd37cSAndy Yan /* 23*08dcd37cSAndy Yan * resource image structure 24*08dcd37cSAndy Yan * ---------------------------------------------- 25*08dcd37cSAndy Yan * | | 26*08dcd37cSAndy Yan * | header (1 block) | 27*08dcd37cSAndy Yan * | | 28*08dcd37cSAndy Yan * ---------------------------------------------| 29*08dcd37cSAndy Yan * | | | 30*08dcd37cSAndy Yan * | entry0 (1 block) | | 31*08dcd37cSAndy Yan * | | | 32*08dcd37cSAndy Yan * ------------------------ | 33*08dcd37cSAndy Yan * | | | 34*08dcd37cSAndy Yan * | entry1 (1 block) | contents (n blocks) | 35*08dcd37cSAndy Yan * | | | 36*08dcd37cSAndy Yan * ------------------------ | 37*08dcd37cSAndy Yan * | ...... | | 38*08dcd37cSAndy Yan * ------------------------ | 39*08dcd37cSAndy Yan * | | | 40*08dcd37cSAndy Yan * | entryn (1 block) | | 41*08dcd37cSAndy Yan * | | | 42*08dcd37cSAndy Yan * ---------------------------------------------- 43*08dcd37cSAndy Yan * | | 44*08dcd37cSAndy Yan * | file0 (x blocks) | 45*08dcd37cSAndy Yan * | | 46*08dcd37cSAndy Yan * ---------------------------------------------- 47*08dcd37cSAndy Yan * | | 48*08dcd37cSAndy Yan * | file1 (y blocks) | 49*08dcd37cSAndy Yan * | | 50*08dcd37cSAndy Yan * ---------------------------------------------- 51*08dcd37cSAndy Yan * | ...... | 52*08dcd37cSAndy Yan * |--------------------------------------------- 53*08dcd37cSAndy Yan * | | 54*08dcd37cSAndy Yan * | filen (z blocks) | 55*08dcd37cSAndy Yan * | | 56*08dcd37cSAndy Yan * ---------------------------------------------- 57*08dcd37cSAndy Yan */ 58*08dcd37cSAndy Yan 59*08dcd37cSAndy Yan /** 60*08dcd37cSAndy Yan * struct resource_image_header 61*08dcd37cSAndy Yan * 62*08dcd37cSAndy Yan * @magic: should be "RSCE" 63*08dcd37cSAndy Yan * @version: resource image version, current is 0 64*08dcd37cSAndy Yan * @c_version: content version, current is 0 65*08dcd37cSAndy Yan * @blks: the size of the header ( 1 block = 512 bytes) 66*08dcd37cSAndy Yan * @c_offset: contents offset(by block) in the image 67*08dcd37cSAndy Yan * @e_blks: the size(by block) of the entry in the contents 68*08dcd37cSAndy Yan * @e_num: numbers of the entrys. 69*08dcd37cSAndy Yan */ 70*08dcd37cSAndy Yan 71*08dcd37cSAndy Yan struct resource_img_hdr { 72*08dcd37cSAndy Yan char magic[4]; 73*08dcd37cSAndy Yan uint16_t version; 74*08dcd37cSAndy Yan uint16_t c_version; 75*08dcd37cSAndy Yan uint8_t blks; 76*08dcd37cSAndy Yan uint8_t c_offset; 77*08dcd37cSAndy Yan uint8_t e_blks; 78*08dcd37cSAndy Yan uint32_t e_nums; 79*08dcd37cSAndy Yan }; 80*08dcd37cSAndy Yan 81*08dcd37cSAndy Yan struct resource_entry { 82*08dcd37cSAndy Yan char tag[4]; 83*08dcd37cSAndy Yan char name[MAX_FILE_NAME_LEN]; 84*08dcd37cSAndy Yan uint32_t f_offset; 85*08dcd37cSAndy Yan uint32_t f_size; 86*08dcd37cSAndy Yan }; 87*08dcd37cSAndy Yan 88*08dcd37cSAndy Yan struct resource_file { 89*08dcd37cSAndy Yan char name[MAX_FILE_NAME_LEN]; 90*08dcd37cSAndy Yan uint32_t f_offset; 91*08dcd37cSAndy Yan uint32_t f_size; 92*08dcd37cSAndy Yan struct list_head link; 93*08dcd37cSAndy Yan }; 94*08dcd37cSAndy Yan 95*08dcd37cSAndy Yan static struct blk_part *rsce_blk; 96*08dcd37cSAndy Yan 97*08dcd37cSAndy Yan static LIST_HEAD(entrys_head); 98*08dcd37cSAndy Yan 99*08dcd37cSAndy Yan static int resource_image_check_header(const struct resource_img_hdr *hdr) 100*08dcd37cSAndy Yan { 101*08dcd37cSAndy Yan int ret; 102*08dcd37cSAndy Yan 103*08dcd37cSAndy Yan ret = memcmp(RESOURCE_MAGIC, hdr->magic, RESOURCE_MAGIC_SIZE); 104*08dcd37cSAndy Yan if (ret) { 105*08dcd37cSAndy Yan printf("bad resource image magic\n"); 106*08dcd37cSAndy Yan ret = -EINVAL; 107*08dcd37cSAndy Yan } 108*08dcd37cSAndy Yan debug("resource image header:\n"); 109*08dcd37cSAndy Yan debug("magic:%s\n", hdr->magic); 110*08dcd37cSAndy Yan debug("version:%d\n", hdr->version); 111*08dcd37cSAndy Yan debug("c_version:%d\n", hdr->c_version); 112*08dcd37cSAndy Yan debug("blks:%d\n", hdr->blks); 113*08dcd37cSAndy Yan debug("c_offset:%d\n", hdr->c_offset); 114*08dcd37cSAndy Yan debug("e_blks:%d\n", hdr->e_blks); 115*08dcd37cSAndy Yan debug("e_num:%d\n", hdr->e_nums); 116*08dcd37cSAndy Yan 117*08dcd37cSAndy Yan return ret; 118*08dcd37cSAndy Yan } 119*08dcd37cSAndy Yan 120*08dcd37cSAndy Yan static int add_file_to_list(struct resource_entry *entry) 121*08dcd37cSAndy Yan { 122*08dcd37cSAndy Yan struct resource_file *file; 123*08dcd37cSAndy Yan 124*08dcd37cSAndy Yan if (memcmp(entry->tag, ENTRY_TAG, ENTRY_TAG_SIZE)) { 125*08dcd37cSAndy Yan printf("invalid entry tag\n"); 126*08dcd37cSAndy Yan return -ENOENT; 127*08dcd37cSAndy Yan } 128*08dcd37cSAndy Yan file = malloc(sizeof(*file)); 129*08dcd37cSAndy Yan if (!file) { 130*08dcd37cSAndy Yan printf("out of memory\n"); 131*08dcd37cSAndy Yan return -ENOMEM; 132*08dcd37cSAndy Yan } 133*08dcd37cSAndy Yan strcpy(file->name, entry->name); 134*08dcd37cSAndy Yan file->f_offset = entry->f_offset; 135*08dcd37cSAndy Yan file->f_size = entry->f_size; 136*08dcd37cSAndy Yan list_add_tail(&file->link, &entrys_head); 137*08dcd37cSAndy Yan debug("entry:%p %s offset:%d size:%d\n", 138*08dcd37cSAndy Yan entry, file->name, file->f_offset, file->f_size); 139*08dcd37cSAndy Yan 140*08dcd37cSAndy Yan return 0; 141*08dcd37cSAndy Yan } 142*08dcd37cSAndy Yan 143*08dcd37cSAndy Yan static int read_file_info_from_blk_dev(void) 144*08dcd37cSAndy Yan { 145*08dcd37cSAndy Yan struct resource_img_hdr *hdr; 146*08dcd37cSAndy Yan struct resource_entry *entry; 147*08dcd37cSAndy Yan void *content; 148*08dcd37cSAndy Yan int size; 149*08dcd37cSAndy Yan int ret; 150*08dcd37cSAndy Yan int e_num; 151*08dcd37cSAndy Yan 152*08dcd37cSAndy Yan rsce_blk = rockchip_get_blk_part(PART_RESOURCE); 153*08dcd37cSAndy Yan if (!rsce_blk) { 154*08dcd37cSAndy Yan printf("no resource partition found\n"); 155*08dcd37cSAndy Yan return -ENODEV; 156*08dcd37cSAndy Yan } 157*08dcd37cSAndy Yan 158*08dcd37cSAndy Yan hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE); 159*08dcd37cSAndy Yan if (!hdr) { 160*08dcd37cSAndy Yan printf("out of memory!\n"); 161*08dcd37cSAndy Yan return -ENOMEM; 162*08dcd37cSAndy Yan } 163*08dcd37cSAndy Yan 164*08dcd37cSAndy Yan ret = blkdev_read(hdr, rsce_blk->from, 1); 165*08dcd37cSAndy Yan if (ret < 0) 166*08dcd37cSAndy Yan goto out; 167*08dcd37cSAndy Yan ret = resource_image_check_header(hdr); 168*08dcd37cSAndy Yan if (ret < 0) 169*08dcd37cSAndy Yan goto out; 170*08dcd37cSAndy Yan content = memalign(ARCH_DMA_MINALIGN, 171*08dcd37cSAndy Yan hdr->e_blks * hdr->e_nums * RK_BLK_SIZE); 172*08dcd37cSAndy Yan if (!content) { 173*08dcd37cSAndy Yan printf("alloc memory for content failed\n"); 174*08dcd37cSAndy Yan goto out; 175*08dcd37cSAndy Yan } 176*08dcd37cSAndy Yan ret = blkdev_read(content, rsce_blk->from + hdr->c_offset, 177*08dcd37cSAndy Yan hdr->e_blks * hdr->e_nums); 178*08dcd37cSAndy Yan if (ret < 0) 179*08dcd37cSAndy Yan goto err; 180*08dcd37cSAndy Yan 181*08dcd37cSAndy Yan for (e_num = 0; e_num < hdr->e_nums; e_num++) { 182*08dcd37cSAndy Yan size = e_num * hdr->e_blks * RK_BLK_SIZE; 183*08dcd37cSAndy Yan entry = (struct resource_entry *)(content + size); 184*08dcd37cSAndy Yan add_file_to_list(entry); 185*08dcd37cSAndy Yan } 186*08dcd37cSAndy Yan 187*08dcd37cSAndy Yan err: 188*08dcd37cSAndy Yan free(content); 189*08dcd37cSAndy Yan out: 190*08dcd37cSAndy Yan free(hdr); 191*08dcd37cSAndy Yan 192*08dcd37cSAndy Yan return 0; 193*08dcd37cSAndy Yan } 194*08dcd37cSAndy Yan 195*08dcd37cSAndy Yan static struct resource_file *get_file_info(struct resource_img_hdr *hdr, 196*08dcd37cSAndy Yan const void *content, 197*08dcd37cSAndy Yan const char *name) 198*08dcd37cSAndy Yan { 199*08dcd37cSAndy Yan struct resource_file *file; 200*08dcd37cSAndy Yan struct list_head *node; 201*08dcd37cSAndy Yan 202*08dcd37cSAndy Yan if (list_empty(&entrys_head)) 203*08dcd37cSAndy Yan read_file_info_from_blk_dev(); 204*08dcd37cSAndy Yan 205*08dcd37cSAndy Yan list_for_each(node, &entrys_head) { 206*08dcd37cSAndy Yan file = list_entry(node, struct resource_file, link); 207*08dcd37cSAndy Yan if (!strcmp(file->name, name)) 208*08dcd37cSAndy Yan return file; 209*08dcd37cSAndy Yan } 210*08dcd37cSAndy Yan 211*08dcd37cSAndy Yan return NULL; 212*08dcd37cSAndy Yan } 213*08dcd37cSAndy Yan 214*08dcd37cSAndy Yan /* 215*08dcd37cSAndy Yan * read file from resource partition 216*08dcd37cSAndy Yan * @buf: destination buf to store file data; 217*08dcd37cSAndy Yan * @name: file name 218*08dcd37cSAndy Yan * @offset: blocks offset in the file, 1 block = 512 bytes 219*08dcd37cSAndy Yan * @len: the size(by bytes) of file to read. 220*08dcd37cSAndy Yan */ 221*08dcd37cSAndy Yan int rockchip_read_resource_file(void *buf, const char *name, 222*08dcd37cSAndy Yan int offset, int len) 223*08dcd37cSAndy Yan { 224*08dcd37cSAndy Yan struct resource_file *file; 225*08dcd37cSAndy Yan int ret = 0; 226*08dcd37cSAndy Yan int blks; 227*08dcd37cSAndy Yan 228*08dcd37cSAndy Yan file = get_file_info(NULL, NULL, name); 229*08dcd37cSAndy Yan if (!file) { 230*08dcd37cSAndy Yan printf("Can't find file:%s\n", name); 231*08dcd37cSAndy Yan return -ENOENT; 232*08dcd37cSAndy Yan } 233*08dcd37cSAndy Yan 234*08dcd37cSAndy Yan if (len <= 0 || len > file->f_size) 235*08dcd37cSAndy Yan len = file->f_size; 236*08dcd37cSAndy Yan blks = DIV_ROUND_UP(len, RK_BLK_SIZE); 237*08dcd37cSAndy Yan ret = blkdev_read(buf, rsce_blk->from + file->f_offset + offset, blks); 238*08dcd37cSAndy Yan if (!ret) 239*08dcd37cSAndy Yan ret = len; 240*08dcd37cSAndy Yan 241*08dcd37cSAndy Yan return ret; 242*08dcd37cSAndy Yan } 243