xref: /rk3399_rockchip-uboot/disk/part_rkparm.c (revision 82198b5ccd31ca903c84f3d16e015ca704af852c)
1*82198b5cSKever Yang /*
2*82198b5cSKever Yang  * (C) Copyright 2017 rkparm Electronics Co., Ltd
3*82198b5cSKever Yang  *
4*82198b5cSKever Yang  * SPDX-License-Identifier:     GPL-2.0+
5*82198b5cSKever Yang  */
6*82198b5cSKever Yang 
7*82198b5cSKever Yang #include <common.h>
8*82198b5cSKever Yang #include <malloc.h>
9*82198b5cSKever Yang 
10*82198b5cSKever Yang #ifdef HAVE_BLOCK_DEVICE
11*82198b5cSKever Yang #define RK_PARAM_OFFSET			0x2000
12*82198b5cSKever Yang #define MAX_PARAM_SIZE			(1024 * 64)
13*82198b5cSKever Yang 
14*82198b5cSKever Yang struct rkparm_param {
15*82198b5cSKever Yang 	u32 tag;
16*82198b5cSKever Yang 	u32 length;
17*82198b5cSKever Yang 	char params[1];
18*82198b5cSKever Yang 	u32 crc;
19*82198b5cSKever Yang };
20*82198b5cSKever Yang 
21*82198b5cSKever Yang struct rkparm_part {
22*82198b5cSKever Yang 	char name[PART_NAME_LEN];
23*82198b5cSKever Yang 	unsigned long start;
24*82198b5cSKever Yang 	unsigned long size;
25*82198b5cSKever Yang 	struct list_head node;
26*82198b5cSKever Yang };
27*82198b5cSKever Yang 
28*82198b5cSKever Yang 
29*82198b5cSKever Yang static LIST_HEAD(parts_head);
30*82198b5cSKever Yang 
31*82198b5cSKever Yang static int rkparm_param_parse(char *param, struct list_head *parts_head)
32*82198b5cSKever Yang {
33*82198b5cSKever Yang 	struct rkparm_part *part;
34*82198b5cSKever Yang 	const char *cmdline = strstr(param, "CMDLINE:");
35*82198b5cSKever Yang 	char *cmdline_end = strstr(cmdline, "\n"); /* end by '\n' */
36*82198b5cSKever Yang 	const char *blkdev_parts = strstr(cmdline, "mtdparts");
37*82198b5cSKever Yang 	const char *blkdev_def = strchr(blkdev_parts, ':') + 1;
38*82198b5cSKever Yang 	char *next = (char *)blkdev_def;
39*82198b5cSKever Yang 	char *pend;
40*82198b5cSKever Yang 	int len;
41*82198b5cSKever Yang 	unsigned long size, start;
42*82198b5cSKever Yang 
43*82198b5cSKever Yang 	if (!cmdline) {
44*82198b5cSKever Yang 		printf("invalid parameter\n");
45*82198b5cSKever Yang 		return -EINVAL;
46*82198b5cSKever Yang 	}
47*82198b5cSKever Yang 
48*82198b5cSKever Yang 	*cmdline_end = '\0';
49*82198b5cSKever Yang 	/* skip "CMDLINE:" */
50*82198b5cSKever Yang 	env_update("bootargs", cmdline + strlen("CMDLINE:"));
51*82198b5cSKever Yang 
52*82198b5cSKever Yang 	while (*next) {
53*82198b5cSKever Yang 		if (*next == '-') {
54*82198b5cSKever Yang 			size = (~0UL);
55*82198b5cSKever Yang 			next++;
56*82198b5cSKever Yang 		} else {
57*82198b5cSKever Yang 			size = simple_strtoul(next, &next, 16);
58*82198b5cSKever Yang 		}
59*82198b5cSKever Yang 		next++;
60*82198b5cSKever Yang 		start = simple_strtoul(next, &next, 16);
61*82198b5cSKever Yang 		next++;
62*82198b5cSKever Yang 		pend =  strchr(next, ')');
63*82198b5cSKever Yang 		if (!pend)
64*82198b5cSKever Yang 			break;
65*82198b5cSKever Yang 		len = min_t(int, pend - next, PART_NAME_LEN);
66*82198b5cSKever Yang 		part = malloc(sizeof(*part));
67*82198b5cSKever Yang 		if (!part) {
68*82198b5cSKever Yang 			printf("out of memory\n");
69*82198b5cSKever Yang 			break;
70*82198b5cSKever Yang 		}
71*82198b5cSKever Yang 		part->start = start;
72*82198b5cSKever Yang 		part->size = size;
73*82198b5cSKever Yang 		strncpy(part->name, next, len);
74*82198b5cSKever Yang 		part->name[len] = '\0';
75*82198b5cSKever Yang 		next = strchr(next, ',');
76*82198b5cSKever Yang 		next++;
77*82198b5cSKever Yang 		list_add_tail(&part->node, parts_head);
78*82198b5cSKever Yang 	}
79*82198b5cSKever Yang 
80*82198b5cSKever Yang 	return 0;
81*82198b5cSKever Yang }
82*82198b5cSKever Yang 
83*82198b5cSKever Yang static int rkparm_init_param(struct blk_desc *dev_desc,
84*82198b5cSKever Yang 				struct list_head *parts_head)
85*82198b5cSKever Yang {
86*82198b5cSKever Yang 	struct rkparm_param *param;
87*82198b5cSKever Yang 	int ret;
88*82198b5cSKever Yang 
89*82198b5cSKever Yang 	param = memalign(ARCH_DMA_MINALIGN, MAX_PARAM_SIZE);
90*82198b5cSKever Yang 	if (!param) {
91*82198b5cSKever Yang 		printf("out of memory\n");
92*82198b5cSKever Yang 		return -ENOMEM;
93*82198b5cSKever Yang 	}
94*82198b5cSKever Yang 
95*82198b5cSKever Yang 	ret = blk_dread(dev_desc, RK_PARAM_OFFSET, MAX_PARAM_SIZE >> 9,
96*82198b5cSKever Yang 			(ulong *)param);
97*82198b5cSKever Yang 	if (ret < 0) {
98*82198b5cSKever Yang 		printf("%s param read fail\n", __func__);
99*82198b5cSKever Yang 		return -EINVAL;
100*82198b5cSKever Yang 	}
101*82198b5cSKever Yang 
102*82198b5cSKever Yang 	return rkparm_param_parse(param->params, parts_head);
103*82198b5cSKever Yang 
104*82198b5cSKever Yang }
105*82198b5cSKever Yang 
106*82198b5cSKever Yang static void part_print_rkparm(struct blk_desc *dev_desc)
107*82198b5cSKever Yang {
108*82198b5cSKever Yang 	int ret = 0;
109*82198b5cSKever Yang 	struct list_head *node;
110*82198b5cSKever Yang 	struct rkparm_part *p = NULL;
111*82198b5cSKever Yang 	int i = 0;
112*82198b5cSKever Yang 
113*82198b5cSKever Yang 	if (list_empty(&parts_head))
114*82198b5cSKever Yang 		ret = rkparm_init_param(dev_desc, &parts_head);
115*82198b5cSKever Yang 
116*82198b5cSKever Yang 	if (ret) {
117*82198b5cSKever Yang 		printf("%s Invalid rkparm parameter\n", __func__);
118*82198b5cSKever Yang 		return;
119*82198b5cSKever Yang 	}
120*82198b5cSKever Yang 
121*82198b5cSKever Yang 	printf("Part\tStart LBA\tSize\t\tName\n");
122*82198b5cSKever Yang 	list_for_each(node, &parts_head) {
123*82198b5cSKever Yang 		p = list_entry(node, struct rkparm_part, node);
124*82198b5cSKever Yang 		printf("%3d\t0x%08lx\t0x%08lx\t%s\n", (i++ + 1),
125*82198b5cSKever Yang 		       p->start, p->size, p->name);
126*82198b5cSKever Yang 	}
127*82198b5cSKever Yang 
128*82198b5cSKever Yang 
129*82198b5cSKever Yang 	return;
130*82198b5cSKever Yang }
131*82198b5cSKever Yang 
132*82198b5cSKever Yang static int part_get_info_rkparm(struct blk_desc *dev_desc, int idx,
133*82198b5cSKever Yang 		      disk_partition_t *info)
134*82198b5cSKever Yang {
135*82198b5cSKever Yang 	struct list_head *node;
136*82198b5cSKever Yang 	struct rkparm_part *p = NULL;
137*82198b5cSKever Yang 	int part_num = 1;
138*82198b5cSKever Yang 	int ret = 0;
139*82198b5cSKever Yang 
140*82198b5cSKever Yang 	if (idx < 1) {
141*82198b5cSKever Yang 		printf("%s Invalid partition no.%d\n", __func__, idx);
142*82198b5cSKever Yang 		return -EINVAL;
143*82198b5cSKever Yang 	}
144*82198b5cSKever Yang 
145*82198b5cSKever Yang 	if (list_empty(&parts_head))
146*82198b5cSKever Yang 		ret = rkparm_init_param(dev_desc, &parts_head);
147*82198b5cSKever Yang 
148*82198b5cSKever Yang 	if (ret) {
149*82198b5cSKever Yang 		printf("%s Invalid rkparm partition\n", __func__);
150*82198b5cSKever Yang 		return -1;
151*82198b5cSKever Yang 	}
152*82198b5cSKever Yang 
153*82198b5cSKever Yang 	list_for_each(node, &parts_head) {
154*82198b5cSKever Yang 		p = list_entry(node, struct rkparm_part, node);
155*82198b5cSKever Yang 		if (idx == part_num)
156*82198b5cSKever Yang 			break;
157*82198b5cSKever Yang 		part_num ++;
158*82198b5cSKever Yang 	}
159*82198b5cSKever Yang 
160*82198b5cSKever Yang 	if (part_num > idx) {
161*82198b5cSKever Yang 		printf("%s Invalid partition no.%d\n", __func__, idx);
162*82198b5cSKever Yang 		return -EINVAL;
163*82198b5cSKever Yang 	}
164*82198b5cSKever Yang 
165*82198b5cSKever Yang 	info->start = p->start;
166*82198b5cSKever Yang 	info->size = p->size << 9;
167*82198b5cSKever Yang 	info->blksz = dev_desc->blksz;
168*82198b5cSKever Yang 
169*82198b5cSKever Yang 	sprintf((char *)info->name, "%s", p->name);
170*82198b5cSKever Yang 	strcpy((char *)info->type, "U-Boot");
171*82198b5cSKever Yang 	info->bootable = 0;
172*82198b5cSKever Yang 
173*82198b5cSKever Yang 	return 0;
174*82198b5cSKever Yang }
175*82198b5cSKever Yang 
176*82198b5cSKever Yang static int part_test_rkparm(struct blk_desc *dev_desc)
177*82198b5cSKever Yang {
178*82198b5cSKever Yang 	int ret = 0;
179*82198b5cSKever Yang 
180*82198b5cSKever Yang 	if (list_empty(&parts_head))
181*82198b5cSKever Yang 		ret = rkparm_init_param(dev_desc, &parts_head);
182*82198b5cSKever Yang 	if (ret)
183*82198b5cSKever Yang 		ret = -1;
184*82198b5cSKever Yang 
185*82198b5cSKever Yang 	return ret;
186*82198b5cSKever Yang }
187*82198b5cSKever Yang /*
188*82198b5cSKever Yang  * Add an 'b_' prefix so it comes before 'dos' and after 'a_efi' in the linker
189*82198b5cSKever Yang  * list. We need to check EFI first, and then rkparm partition
190*82198b5cSKever Yang  */
191*82198b5cSKever Yang U_BOOT_PART_TYPE(b_rkparm) = {
192*82198b5cSKever Yang 	.name		= "RKPARM",
193*82198b5cSKever Yang 	.part_type	= PART_TYPE_RKPARM,
194*82198b5cSKever Yang 	.max_entries	= GPT_ENTRY_NUMBERS,
195*82198b5cSKever Yang 	.get_info	= part_get_info_ptr(part_get_info_rkparm),
196*82198b5cSKever Yang 	.print		= part_print_ptr(part_print_rkparm),
197*82198b5cSKever Yang 	.test		= part_test_rkparm,
198*82198b5cSKever Yang };
199*82198b5cSKever Yang #endif
200