1 /*
2 * (C) Copyright 2021 rkparm Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <malloc.h>
9 #include <asm/arch/rk_atags.h>
10
11 struct rkram_part {
12 char name[PART_NAME_LEN];
13 ulong start;
14 ulong size;
15 struct list_head node;
16 };
17
18 static LIST_HEAD(parts_head);
19
rkram_part_init(struct blk_desc * dev_desc,struct list_head * parts_head)20 static int rkram_part_init(struct blk_desc *dev_desc,
21 struct list_head *parts_head)
22 {
23 struct rkram_part *part;
24 struct tag *t;
25 int i, len;
26 u64 start;
27 u64 size;
28
29 if (!atags_is_available()) {
30 debug("%s: No ATAGS\n", __func__);
31 return -ENODATA;
32 }
33
34 t = atags_get_tag(ATAG_RAM_PARTITION);
35 if (!t) {
36 debug("%s: No ATAGS ramdisk partition\n", __func__);
37 return -ENODATA;
38 }
39
40 INIT_LIST_HEAD(parts_head);
41
42 for (i = 0; i < t->u.ram_part.count; i++) {
43 part = malloc(sizeof(*part));
44 if (!part) {
45 printf("%s: No memory\n", __func__);
46 break;
47 }
48
49 len = strlen(t->u.ram_part.part[i].name) + 1;
50 memcpy((char *)&part->name,
51 (char *)&t->u.ram_part.part[i].name, len);
52 start = t->u.ram_part.part[i].start;
53 size = t->u.ram_part.part[i].size;
54
55 if (!IS_ALIGNED(start, dev_desc->blksz)) {
56 printf("%s: addr 0x%llx is not %ld align\n",
57 part->name, start, dev_desc->blksz);
58 return -EINVAL;
59 } else if (!IS_ALIGNED(size, dev_desc->blksz)) {
60 printf("%s: size 0x%llx is not %ld align\n",
61 part->name, size, dev_desc->blksz);
62 return -EINVAL;
63 }
64
65 /* bytes to blksz */
66 part->start = start / dev_desc->blksz;
67 part->size = size / dev_desc->blksz;
68 list_add_tail(&part->node, parts_head);
69
70 debug("%s: name=%s, start=0x%lx, size=0x%lx, blksz=0x%lx\n",
71 __func__, part->name, part->start,
72 part->size, dev_desc->blksz);
73 }
74
75 return 0;
76 }
77
part_print_rkram_part(struct blk_desc * dev_desc)78 static void part_print_rkram_part(struct blk_desc *dev_desc)
79 {
80 struct list_head *node;
81 struct rkram_part *p;
82 int i = 0;
83
84 if (list_empty(&parts_head)) {
85 printf("No Partition Table\n");
86 return;
87 }
88
89 printf("Part\tStart LBA\tSize\t\tName\n");
90 list_for_each(node, &parts_head) {
91 p = list_entry(node, struct rkram_part, node);
92 printf("%3d\t0x%08lx\t0x%08lx\t%s\n", (i++ + 1),
93 p->start, p->size, p->name);
94 }
95 }
96
part_get_info_rkram_part(struct blk_desc * dev_desc,int idx,disk_partition_t * info)97 static int part_get_info_rkram_part(struct blk_desc *dev_desc, int idx,
98 disk_partition_t *info)
99 {
100 struct rkram_part *p = NULL;
101 struct list_head *node;
102 int part_num = 1;
103
104 if (idx < 1) {
105 printf("Invalid partition no.%d\n", idx);
106 return -EINVAL;
107 }
108
109 if (list_empty(&parts_head))
110 return -EINVAL;
111
112 list_for_each(node, &parts_head) {
113 p = list_entry(node, struct rkram_part, node);
114 if (idx == part_num)
115 break;
116 part_num++;
117 }
118
119 if (part_num < idx) {
120 debug("%s Invalid partition no.%d\n", __func__, idx);
121 return -EINVAL;
122 }
123
124 info->start = p->start;
125 info->size = p->size;
126 info->blksz = dev_desc->blksz;
127
128 sprintf((char *)info->name, "%s", p->name);
129 strcpy((char *)info->type, "U-Boot");
130 info->bootable = 0;
131
132 return 0;
133 }
134
part_test_rkram_part(struct blk_desc * dev_desc)135 static int part_test_rkram_part(struct blk_desc *dev_desc)
136 {
137 return rkram_part_init(dev_desc, &parts_head);
138 }
139
140 /*
141 * Add an 'a_a_' prefix so it comes before 'dos' and after 'a_efi'
142 * in the linker list. We need to check this first.
143 */
144 U_BOOT_PART_TYPE(a_a_rkram_part) = {
145 .name = "RKRAM_PART",
146 .part_type = PART_TYPE_RKRAM,
147 .max_entries = RKRAM_ENTRY_NUMBERS,
148 .get_info = part_get_info_ptr(part_get_info_rkram_part),
149 .print = part_print_ptr(part_print_rkram_part),
150 .test = part_test_rkram_part,
151 };
152