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