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