blob: bd7d3826990b39396e81fb97f819ec77fe19fa73 [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}
194#endif
195
196int get_partition_from_dts(unsigned char *buffer)
197{
198 char *dt_addr;
199 int nodeoffset,poffset=0;
200 int *parts_num;
201 char propname[8];
202 const uint32_t *phandle;
203 const char *uname;
204 const char *usize;
205 const char *umask;
206 int index;
207 int ret = -1;
208#if CONFIG_IS_ENABLED(EFI_PARTITION)
209 struct blk_desc *dev_desc;
210
211 if (!buffer)
212 goto _err;
213
214 dev_desc = (struct blk_desc *)malloc(sizeof(struct blk_desc));
215 if (!dev_desc)
216 goto _err;
217
218 dev_desc->blksz = MMC_BLOCK_SIZE;
219 dev_desc->lba = GPT_SPACE;
220
221 if (!is_valid_gpt_buf(dev_desc, buffer)) {
222 if (!parse_gpt(dev_desc, buffer)) {
223 gpt_partition = true;
224 free(dev_desc);
225 return 0;
226 }
227 }
228 free(dev_desc);
229#endif
230
231 ret = check_valid_dts(buffer);
232 printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
233 if ( ret < 0 )
234 {
235 printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
236 goto _err;
237 }
238#ifdef CONFIG_MULTI_DTB
239 dt_addr = (char *)get_multi_dt_entry((unsigned long)buffer);
240#else
241 dt_addr = (char *)buffer;
242#endif
243 nodeoffset = fdt_path_offset(dt_addr, "/partitions");
244 if (nodeoffset < 0)
245 {
246 printf("%s: not find /partitions node %s.\n",__func__,fdt_strerror(nodeoffset));
247 ret = -1;
248 goto _err;
249 }
250 parts_num = (int *)fdt_getprop(dt_addr, nodeoffset, "parts", NULL);
251 if (!parts_num) {
252 printf("%s parts_num _err\n", __func__);
253 return -1;
254 }
255
256 printf("parts: %d\n", be32_to_cpup((u32 *)parts_num));
257 if (*parts_num > 0) {
258 part_table = (struct partitions *)malloc(sizeof(struct partitions) *
259 (be32_to_cpup((u32 *)parts_num)));
260 if (!part_table) {
261 printf("%s part_table alloc _err\n", __func__);
262 return -1;
263 }
264 memset(part_table, 0, sizeof(struct partitions)*(be32_to_cpup((u32*)parts_num)));
265 parts_total_num = be32_to_cpup((u32*)parts_num);
266 }
267 dynamic_partition = false;
268 env_set("partition_mode","normal");
269 vendor_boot_partition = false;
270 env_set("vendor_boot_mode","false");
271 for (index = 0; index < be32_to_cpup((u32*)parts_num); index++)
272 {
273 sprintf(propname,"part-%d", index);
274
275 phandle = fdt_getprop(dt_addr, nodeoffset, propname, NULL);
276 if (!phandle) {
277 printf("don't find match part-%d\n",index);
278 goto _err;
279 }
280 if (phandle) {
281 poffset = fdt_node_offset_by_phandle(dt_addr, be32_to_cpup((u32*)phandle));
282 if (!poffset) {
283 printf("%s:%d,can't find device node\n",__func__,__LINE__);
284 goto _err;
285 }
286 }
287 uname = fdt_getprop(dt_addr, poffset, "pname", NULL);
288 //printf("%s:%d uname: %s\n",__func__,__LINE__, uname);
289 /* a string but not */
290 usize = fdt_getprop(dt_addr, poffset, "size", NULL);
291 //printf("%s:%d size: 0x%x 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)usize), be32_to_cpup((((u32*)usize)+1)));
292 umask = fdt_getprop(dt_addr, poffset, "mask", NULL);
293 //printf("%s:%d mask: 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)umask));
294 /* fill partition table */
295 if (uname != NULL)
296 memcpy(part_table[index].name, uname, strlen(uname));
297 part_table[index].size = ((unsigned long)be32_to_cpup((u32*)usize) << 32) | (unsigned long)be32_to_cpup((((u32*)usize)+1));
298 part_table[index].mask_flags = be32_to_cpup((u32*)umask);
299 printf("%02d:%10s\t%016llx %01x\n", index, uname, part_table[index].size, part_table[index].mask_flags);
300
301 if (strcmp(uname, "boot_a") == 0) {
302 has_boot_slot = 1;
303 printf("set has_boot_slot = 1\n");
304 }
305 else if (strcmp(uname, "boot") == 0) {
306 has_boot_slot = 0;
307 printf("set has_boot_slot = 0\n");
308 }
309 if (strcmp(uname, "system_a") == 0)
310 has_system_slot = 1;
311 else if (strcmp(uname, "system") == 0)
312 has_system_slot = 0;
313
314 if (strcmp(uname, "super") == 0) {
315 dynamic_partition = true;
316 env_set("partition_mode","dynamic");
317 printf("enable dynamic_partition\n");
318 }
319
320 if (strncmp(uname, "vendor_boot", 11) == 0) {
321 vendor_boot_partition = true;
322 env_set("vendor_boot_mode","true");
323 printf("enable vendor_boot\n");
324 }
325 }
326 /*enable mmc_device_init when dtb is update from ddr*/
327 is_partition_checked = false;
328 return 0;
329
330_err:
331 if (part_table != NULL) {
332 free(part_table);
333 part_table = NULL;
334 }
335 return ret;
336}