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