blob: 2b5abfaa4d96ad3fab067f045a15555c43428924 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <malloc.h>
8#include <linux/err.h>
9#include <amlogic/partition_table.h>
10#include <linux/libfdt.h>
11#include <asm/amlogic/arch/bl31_apis.h>
12#include <amlogic/aml_efuse.h>
13#include <part_efi.h>
14#include <blk.h>
15#include <compiler.h>
16#include <mmc.h>
17#include <amlogic/emmc_partitions.h>
18#include <version.h>
19#include <amlogic/image_check.h>
20
21#ifdef CONFIG_MULTI_DTB
22 extern unsigned long get_multi_dt_entry(unsigned long fdt_addr);
23#endif
24
25#define GPT_SPACE 0X2000
26
27struct partitions_data{
28 int nr;
29 struct partitions *parts;
30};
31
32struct partitions *part_table = NULL;
33int parts_total_num;
34int has_boot_slot = 0;
35int has_system_slot = 0;
36bool dynamic_partition = false;
37bool vendor_boot_partition = false;
38bool is_partition_checked = false;
39#if CONFIG_IS_ENABLED(EFI_PARTITION)
40bool gpt_partition;
41#endif
42
43int get_partitions_table(struct partitions **table)
44{
45 int ret = 0;
46 if (part_table && parts_total_num) {
47 *table = part_table;
48 ret = parts_total_num;
49 }
50 return ret;
51}
52int get_partition_count(void)
53{
54 return parts_total_num;
55}
56struct partitions *get_partitions(void)
57{
58 return part_table;
59}
60
61void free_partitions(void)
62{
63 if (part_table)
64 free(part_table);
65 part_table = NULL;
66}
67
68/*
69 return 0 if dts is valid
70 other value are falure.
71*/
72int check_valid_dts(unsigned char *buffer)
73{
74 int ret = -__LINE__;
75 char *dt_addr;
76 /* fixme, a work around way */
77#ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK
78 unsigned char *sbuffer = (unsigned char *)env_get_hex("loadaddr", 0x1000000 + 0x100000);
79 ulong ncheckoffset = 0;
80 /* g12a merge to trunk, use trunk code */
81 //unsigned char *sbuffer = (unsigned char *)0x1000000;
82
83 if (IS_FEAT_BOOT_VERIFY()) {
84 memcpy(sbuffer, buffer, AML_DTB_IMG_MAX_SZ);
85 flush_cache((unsigned long)sbuffer, AML_DTB_IMG_MAX_SZ);
86#ifndef CONFIG_IMAGE_CHECK
87 ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, (long unsigned)sbuffer, AML_DTB_IMG_MAX_SZ, 0);
88#else
89 ret = secure_image_check((uint8_t *)(unsigned long)sbuffer, AML_DTB_IMG_MAX_SZ, 0);
90 ncheckoffset = sizeof(struct aml_boot_header_t);
91#endif
92 if (ret) {
93 printf("\n %s() %d: Decrypt dtb: Sig Check %d\n", __func__, __LINE__, ret);
94 return -__LINE__;
95 }
96 memcpy(buffer, sbuffer + ncheckoffset, AML_DTB_IMG_MAX_SZ);
97 }
98#endif
99#ifdef CONFIG_MULTI_DTB
100 dt_addr = (char *)get_multi_dt_entry((unsigned long)buffer);
101#else
102 dt_addr = (char *)buffer;
103#endif
104 pr_debug("start dts,buffer=%p,dt_addr=%p\n", buffer, dt_addr);
105 ret = fdt_check_header(dt_addr);
106 if ( ret < 0 )
107 printf("%s: %s\n",__func__,fdt_strerror(ret));
108 /* fixme, is it 0 when ok? */
109 return ret;
110}
111
112#if CONFIG_IS_ENABLED(EFI_PARTITION)
113int parse_gpt(struct blk_desc *dev_desc, void *buf)
114{
115 gpt_header *gpt_h;
116 gpt_entry *gpt_e;
117 size_t efiname_len, dosname_len;
118 int parts_num = 0;
119 int i, k;
120
121 /* determine start of GPT Header in the buffer */
122 gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
123 dev_desc->blksz);
124
125 /* determine start of GPT Entries in the buffer */
126 gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
127 dev_desc->blksz);
128
129 parts_num = le32_to_cpu(gpt_h->num_partition_entries);
130 if (parts_num > 0) {
131 part_table = (struct partitions *)
132 malloc(sizeof(struct partitions) * parts_num);
133 if (!part_table) {
134 printf("%s part_table alloc _err\n", __func__);
135 return -1;
136 }
137 memset(part_table, 0, sizeof(struct partitions) * parts_num);
138 parts_total_num = parts_num;
139 }
140
141 dynamic_partition = false;
142 env_set("partition_mode", "normal");
143 vendor_boot_partition = false;
144 env_set("vendor_boot_mode", "false");
145
146 for (i = 0; i < parts_num; i++) {
147 if (!is_pte_valid(&gpt_e[i])) {
148 free(part_table);
149 return -1;
150 }
151
152 part_table[i].offset = le64_to_cpu(gpt_e[i].starting_lba << 9ULL);
153 part_table[i].size = ((le64_to_cpu(gpt_e[i].ending_lba) + 1) -
154 le64_to_cpu(gpt_e[i].starting_lba)) << 9ULL;
155 /* mask flag */
156 part_table[i].mask_flags =
157 (uint32_t)le64_to_cpu(gpt_e[i].attributes.fields.type_guid_specific);
158 /* partition name */
159 efiname_len = sizeof(gpt_e[i].partition_name) / sizeof(efi_char16_t);
160 dosname_len = sizeof(part_table[i].name);
161
162 memset(part_table[i].name, 0, sizeof(part_table[i].name));
163 for (k = 0; k < min(dosname_len, efiname_len); k++)
164 part_table[i].name[k] = (char)gpt_e[i].partition_name[k];
165
166 if (strcmp(part_table[i].name, "boot_a") == 0) {
167 has_boot_slot = 1;
168 printf("set has_boot_slot = 1\n");
169 } else if (strcmp(part_table[i].name, "boot") == 0) {
170 has_boot_slot = 0;
171 printf("set has_boot_slot = 0\n");
172 }
173
174 if (strcmp(part_table[i].name, "system_a") == 0)
175 has_system_slot = 1;
176 else if (strcmp(part_table[i].name, "system") == 0)
177 has_system_slot = 0;
178
179 if (strcmp(part_table[i].name, "super") == 0) {
180 dynamic_partition = true;
181 env_set("partition_mode", "dynamic");
182 printf("enable dynamic_partition\n");
183 }
184
185 if (strncmp(part_table[i].name, "vendor_boot", 11) == 0) {
186 vendor_boot_partition = true;
187 env_set("vendor_boot_mode", "true");
188 printf("enable vendor_boot\n");
189 }
190 }
191 is_partition_checked = false;
192 return 0;
193}
ruixuan.li554d4e92023-02-28 17:11:25 +0800194
195int get_partition_from_gpt(unsigned char *buffer)
196{
197 int ret = -1;
198 struct blk_desc *dev_desc;
199 struct mmc *mmc;
200
201 if (!buffer)
202 return ret;
203
204 mmc = find_mmc_device(STORAGE_EMMC);
205 if (!mmc)
206 return 1;
207
208 dev_desc = mmc_get_blk_desc(mmc);
209 if (!dev_desc)
210 return ret;
211
212 check_gpt_part(dev_desc, buffer);
213 if (!is_valid_gpt_buf(dev_desc, buffer)) {
214 if (!parse_gpt(dev_desc, buffer)) {
215 gpt_partition = true;
216 mmc_partition_init();
217 return 0;
218 }
219 }
220
221 return ret;
222}
Bo Lv72d0e902023-01-02 14:27:34 +0000223#endif
224
ruixuan.li554d4e92023-02-28 17:11:25 +0800225/*uboot 2023 abandon this function*/
Bo Lv72d0e902023-01-02 14:27:34 +0000226int get_partition_from_dts(unsigned char *buffer)
227{
228 char *dt_addr;
229 int nodeoffset,poffset=0;
230 int *parts_num;
231 char propname[8];
232 const uint32_t *phandle;
233 const char *uname;
234 const char *usize;
235 const char *umask;
236 int index;
237 int ret = -1;
238#if CONFIG_IS_ENABLED(EFI_PARTITION)
239 struct blk_desc *dev_desc;
240
241 if (!buffer)
242 goto _err;
243
244 dev_desc = (struct blk_desc *)malloc(sizeof(struct blk_desc));
245 if (!dev_desc)
246 goto _err;
247
248 dev_desc->blksz = MMC_BLOCK_SIZE;
249 dev_desc->lba = GPT_SPACE;
250
251 if (!is_valid_gpt_buf(dev_desc, buffer)) {
252 if (!parse_gpt(dev_desc, buffer)) {
253 gpt_partition = true;
254 free(dev_desc);
255 return 0;
256 }
257 }
258 free(dev_desc);
259#endif
260
261 ret = check_valid_dts(buffer);
262 printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
263 if ( ret < 0 )
264 {
265 printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
266 goto _err;
267 }
268#ifdef CONFIG_MULTI_DTB
269 dt_addr = (char *)get_multi_dt_entry((unsigned long)buffer);
270#else
271 dt_addr = (char *)buffer;
272#endif
273 nodeoffset = fdt_path_offset(dt_addr, "/partitions");
274 if (nodeoffset < 0)
275 {
276 printf("%s: not find /partitions node %s.\n",__func__,fdt_strerror(nodeoffset));
277 ret = -1;
278 goto _err;
279 }
280 parts_num = (int *)fdt_getprop(dt_addr, nodeoffset, "parts", NULL);
281 if (!parts_num) {
282 printf("%s parts_num _err\n", __func__);
283 return -1;
284 }
285
286 printf("parts: %d\n", be32_to_cpup((u32 *)parts_num));
287 if (*parts_num > 0) {
288 part_table = (struct partitions *)malloc(sizeof(struct partitions) *
289 (be32_to_cpup((u32 *)parts_num)));
290 if (!part_table) {
291 printf("%s part_table alloc _err\n", __func__);
292 return -1;
293 }
294 memset(part_table, 0, sizeof(struct partitions)*(be32_to_cpup((u32*)parts_num)));
295 parts_total_num = be32_to_cpup((u32*)parts_num);
296 }
297 dynamic_partition = false;
298 env_set("partition_mode","normal");
299 vendor_boot_partition = false;
300 env_set("vendor_boot_mode","false");
301 for (index = 0; index < be32_to_cpup((u32*)parts_num); index++)
302 {
303 sprintf(propname,"part-%d", index);
304
305 phandle = fdt_getprop(dt_addr, nodeoffset, propname, NULL);
306 if (!phandle) {
307 printf("don't find match part-%d\n",index);
308 goto _err;
309 }
310 if (phandle) {
311 poffset = fdt_node_offset_by_phandle(dt_addr, be32_to_cpup((u32*)phandle));
312 if (!poffset) {
313 printf("%s:%d,can't find device node\n",__func__,__LINE__);
314 goto _err;
315 }
316 }
317 uname = fdt_getprop(dt_addr, poffset, "pname", NULL);
318 //printf("%s:%d uname: %s\n",__func__,__LINE__, uname);
319 /* a string but not */
320 usize = fdt_getprop(dt_addr, poffset, "size", NULL);
321 //printf("%s:%d size: 0x%x 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)usize), be32_to_cpup((((u32*)usize)+1)));
322 umask = fdt_getprop(dt_addr, poffset, "mask", NULL);
323 //printf("%s:%d mask: 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)umask));
324 /* fill partition table */
325 if (uname != NULL)
326 memcpy(part_table[index].name, uname, strlen(uname));
327 part_table[index].size = ((unsigned long)be32_to_cpup((u32*)usize) << 32) | (unsigned long)be32_to_cpup((((u32*)usize)+1));
328 part_table[index].mask_flags = be32_to_cpup((u32*)umask);
329 printf("%02d:%10s\t%016llx %01x\n", index, uname, part_table[index].size, part_table[index].mask_flags);
330
331 if (strcmp(uname, "boot_a") == 0) {
332 has_boot_slot = 1;
333 printf("set has_boot_slot = 1\n");
334 }
335 else if (strcmp(uname, "boot") == 0) {
336 has_boot_slot = 0;
337 printf("set has_boot_slot = 0\n");
338 }
339 if (strcmp(uname, "system_a") == 0)
340 has_system_slot = 1;
341 else if (strcmp(uname, "system") == 0)
342 has_system_slot = 0;
343
344 if (strcmp(uname, "super") == 0) {
345 dynamic_partition = true;
346 env_set("partition_mode","dynamic");
347 printf("enable dynamic_partition\n");
348 }
349
350 if (strncmp(uname, "vendor_boot", 11) == 0) {
351 vendor_boot_partition = true;
352 env_set("vendor_boot_mode","true");
353 printf("enable vendor_boot\n");
354 }
355 }
356 /*enable mmc_device_init when dtb is update from ddr*/
357 is_partition_checked = false;
358 return 0;
359
360_err:
361 if (part_table != NULL) {
362 free(part_table);
363 part_table = NULL;
364 }
365 return ret;
366}