1 /*
2 * (C) Copyright 2021 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6 #include <common.h>
7 #include <boot_rkimg.h>
8 #include <div64.h>
9 #include <dfu.h>
10 #include <errno.h>
11 #include <linux/mtd/mtd.h>
12 #include <malloc.h>
13 #include <part.h>
14
dfu_write_medium_mtd(struct dfu_entity * dfu,u64 offset,void * buf,long * len)15 static int dfu_write_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, long *len)
16 {
17 struct blk_desc *dev_desc;
18 u64 block_start, block_len;
19 int ret = -ENODEV;
20
21 switch (dfu->layout) {
22 case DFU_RAW_ADDR:
23 /* if buf == NULL return total size of the area */
24 if (!buf) {
25 *len = dfu->data.nand.size;
26 return 0;
27 }
28
29 dev_desc = rockchip_get_bootdev();
30 if (!dev_desc) {
31 printf("%s: dev_desc is NULL!\n", __func__);
32 return -ENODEV;
33 }
34
35 /* in case of ubi partition, erase rest of the partition */
36 if (dfu->data.mtd.ubi && !offset) {
37 block_start = dfu->data.mtd.start >> 9;
38 block_len = dfu->data.mtd.size >> 9;
39
40 ret = blk_derase(dev_desc, block_start, block_len);
41 if (ret != 0)
42 printf("Failure erase: %d\n", ret);
43 }
44
45 block_start = (dfu->data.mtd.start + offset) >> 9;
46 block_len = (*len) >> 9;
47
48 ret = blk_dwrite(dev_desc, block_start, block_len, buf);
49 if (ret == block_len)
50 ret = 0;
51 break;
52 default:
53 printf("%s: Layout (%s) not (yet) supported!\n", __func__,
54 dfu_get_layout(dfu->layout));
55 }
56
57 return ret;
58 }
59
dfu_get_medium_size_mtd(struct dfu_entity * dfu,u64 * size)60 static int dfu_get_medium_size_mtd(struct dfu_entity *dfu, u64 *size)
61 {
62 *size = dfu->data.mtd.size;
63
64 return 0;
65 }
66
dfu_read_medium_mtd(struct dfu_entity * dfu,u64 offset,void * buf,long * len)67 static int dfu_read_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, long *len)
68 {
69 struct blk_desc *dev_desc;
70 u64 block_start, block_len;
71 int ret = -ENODEV;
72
73 switch (dfu->layout) {
74 case DFU_RAW_ADDR:
75 /* if buf == NULL return total size of the area */
76 if (!buf) {
77 *len = dfu->data.nand.size;
78 return 0;
79 }
80
81 dev_desc = rockchip_get_bootdev();
82 if (!dev_desc) {
83 printf("%s: dev_desc is NULL!\n", __func__);
84 return -ENODEV;
85 }
86
87 block_start = (dfu->data.mtd.start + offset) >> 9;
88 block_len = (*len) >> 9;
89
90 ret = blk_dread(dev_desc, block_start, block_len, buf);
91 if (ret == block_len)
92 ret = 0;
93 break;
94 default:
95 printf("%s: Layout (%s) not (yet) supported!\n", __func__,
96 dfu_get_layout(dfu->layout));
97 }
98
99 return ret;
100 }
101
dfu_flush_medium_mtd(struct dfu_entity * dfu)102 static int dfu_flush_medium_mtd(struct dfu_entity *dfu)
103 {
104 return 0;
105 }
106
dfu_polltimeout_mtd(struct dfu_entity * dfu)107 unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu)
108 {
109 /*
110 * Currently, Poll Timeout != 0 is only needed on nand
111 * ubi partition, as the not used sectors need an erase
112 */
113 if (dfu->data.mtd.ubi)
114 return DFU_MANIFEST_POLL_TIMEOUT;
115
116 return DFU_DEFAULT_POLL_TIMEOUT;
117 }
118
dfu_fill_entity_mtd(struct dfu_entity * dfu,char * devstr,char * s)119 int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s)
120 {
121 struct blk_desc *dev_desc;
122 disk_partition_t dfu_part;
123 char *st;
124
125 dfu->data.mtd.ubi = 0;
126 dfu->dev_type = DFU_DEV_MTD;
127 st = strsep(&s, " ");
128
129 if (!strcmp(st, "raw") || !strcmp(st, "rawubi")) {
130 dfu->layout = DFU_RAW_ADDR;
131 dfu->data.mtd.start = simple_strtoul(s, &s, 16);
132 s++;
133 dfu->data.mtd.size = simple_strtoul(s, &s, 16);
134 if (!strcmp(st, "rawubi"))
135 dfu->data.mtd.ubi = 1;
136 } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) {
137 dev_desc = rockchip_get_bootdev();
138 if (!dev_desc) {
139 printf("%s: dev_desc is NULL!\n", __func__);
140 return -ENODEV;
141 }
142 dfu->layout = DFU_RAW_ADDR;
143 if (part_get_info_by_name(dev_desc, s, &dfu_part) < 0)
144 return -EIO;
145
146 dfu->data.mtd.start = dfu_part.start << 9;
147 dfu->data.mtd.size = dfu_part.size << 9;
148 if (!strcmp(st, "partubi"))
149 dfu->data.mtd.ubi = 1;
150 } else {
151 printf("%s: Memory layout (%s) not supported!\n", __func__, st);
152 return -1;
153 }
154
155 dfu->get_medium_size = dfu_get_medium_size_mtd;
156 dfu->read_medium = dfu_read_medium_mtd;
157 dfu->write_medium = dfu_write_medium_mtd;
158 dfu->flush_medium = dfu_flush_medium_mtd;
159 dfu->poll_timeout = dfu_polltimeout_mtd;
160
161 /* initial state */
162 dfu->inited = 0;
163
164 return 0;
165 }
166