Commit bf8940d35b91ef87e0e4e691c5d8cc356fcae035
Committed by
Tom Rini
1 parent
1f8690aa95
Exists in
v2017.01-smarct4x
and in
30 other branches
fastboot: Implement NAND backend
So far the fastboot code was only supporting MMC-backed devices for its flashing operations (flash and erase). Add a storage backend for NAND-backed devices. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Showing 4 changed files with 223 additions and 1 deletions Side-by-side Diff
common/Makefile
... | ... | @@ -276,9 +276,14 @@ |
276 | 276 | obj-y += stdio.o |
277 | 277 | |
278 | 278 | # This option is not just y/n - it can have a numeric value |
279 | -ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV | |
279 | +ifdef CONFIG_FASTBOOT_FLASH | |
280 | 280 | obj-y += aboot.o |
281 | +ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV | |
281 | 282 | obj-y += fb_mmc.o |
283 | +endif | |
284 | +ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV | |
285 | +obj-y += fb_nand.o | |
286 | +endif | |
282 | 287 | endif |
283 | 288 | |
284 | 289 | obj-$(CONFIG_CMD_BLOB) += cmd_blob.o |
common/fb_nand.c
1 | +/* | |
2 | + * Copyright 2014 Broadcom Corporation. | |
3 | + * Copyright 2015 Free Electrons. | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#include <config.h> | |
9 | +#include <common.h> | |
10 | + | |
11 | +#include <aboot.h> | |
12 | +#include <fastboot.h> | |
13 | +#include <sparse_format.h> | |
14 | + | |
15 | +#include <linux/mtd/mtd.h> | |
16 | +#include <jffs2/jffs2.h> | |
17 | +#include <nand.h> | |
18 | + | |
19 | +static char *response_str; | |
20 | + | |
21 | +struct fb_nand_sparse { | |
22 | + nand_info_t *nand; | |
23 | + struct part_info *part; | |
24 | +}; | |
25 | + | |
26 | +static int fb_nand_lookup(const char *partname, char *response, | |
27 | + nand_info_t **nand, | |
28 | + struct part_info **part) | |
29 | +{ | |
30 | + struct mtd_device *dev; | |
31 | + int ret; | |
32 | + u8 pnum; | |
33 | + | |
34 | + ret = mtdparts_init(); | |
35 | + if (ret) { | |
36 | + error("Cannot initialize MTD partitions\n"); | |
37 | + fastboot_fail(response_str, "cannot init mtdparts"); | |
38 | + return ret; | |
39 | + } | |
40 | + | |
41 | + ret = find_dev_and_part(partname, &dev, &pnum, part); | |
42 | + if (ret) { | |
43 | + error("cannot find partition: '%s'", partname); | |
44 | + fastboot_fail(response_str, "cannot find partition"); | |
45 | + return ret; | |
46 | + } | |
47 | + | |
48 | + if (dev->id->type != MTD_DEV_TYPE_NAND) { | |
49 | + error("partition '%s' is not stored on a NAND device", | |
50 | + partname); | |
51 | + fastboot_fail(response_str, "not a NAND device"); | |
52 | + return -EINVAL; | |
53 | + } | |
54 | + | |
55 | + *nand = &nand_info[dev->id->num]; | |
56 | + | |
57 | + return 0; | |
58 | +} | |
59 | + | |
60 | +static int _fb_nand_erase(nand_info_t *nand, struct part_info *part) | |
61 | +{ | |
62 | + nand_erase_options_t opts; | |
63 | + int ret; | |
64 | + | |
65 | + memset(&opts, 0, sizeof(opts)); | |
66 | + opts.offset = part->offset; | |
67 | + opts.length = part->size; | |
68 | + opts.quiet = 1; | |
69 | + | |
70 | + printf("Erasing blocks 0x%llx to 0x%llx\n", | |
71 | + part->offset, part->offset + part->size); | |
72 | + | |
73 | + ret = nand_erase_opts(nand, &opts); | |
74 | + if (ret) | |
75 | + return ret; | |
76 | + | |
77 | + printf("........ erased 0x%llx bytes from '%s'\n", | |
78 | + part->size, part->name); | |
79 | + | |
80 | + return 0; | |
81 | +} | |
82 | + | |
83 | +static int _fb_nand_write(nand_info_t *nand, struct part_info *part, | |
84 | + void *buffer, unsigned int offset, | |
85 | + unsigned int length, size_t *written) | |
86 | +{ | |
87 | + int flags = WITH_WR_VERIFY; | |
88 | + | |
89 | +#ifdef CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS | |
90 | + flags |= WITH_DROP_FFS; | |
91 | +#endif | |
92 | + | |
93 | + return nand_write_skip_bad(nand, offset, &length, written, | |
94 | + part->size - (offset - part->offset), | |
95 | + buffer, flags); | |
96 | +} | |
97 | + | |
98 | +static int fb_nand_sparse_write(struct sparse_storage *storage, | |
99 | + void *priv, | |
100 | + unsigned int offset, | |
101 | + unsigned int size, | |
102 | + char *data) | |
103 | +{ | |
104 | + struct fb_nand_sparse *sparse = priv; | |
105 | + size_t written; | |
106 | + int ret; | |
107 | + | |
108 | + ret = _fb_nand_write(sparse->nand, sparse->part, data, | |
109 | + offset * storage->block_sz, | |
110 | + size * storage->block_sz, &written); | |
111 | + if (ret < 0) { | |
112 | + printf("Failed to write sparse chunk\n"); | |
113 | + return ret; | |
114 | + } | |
115 | + | |
116 | + return written / storage->block_sz; | |
117 | +} | |
118 | + | |
119 | +void fb_nand_flash_write(const char *partname, unsigned int session_id, | |
120 | + void *download_buffer, unsigned int download_bytes, | |
121 | + char *response) | |
122 | +{ | |
123 | + struct part_info *part; | |
124 | + nand_info_t *nand = NULL; | |
125 | + int ret; | |
126 | + | |
127 | + /* initialize the response buffer */ | |
128 | + response_str = response; | |
129 | + | |
130 | + ret = fb_nand_lookup(partname, response, &nand, &part); | |
131 | + if (ret) { | |
132 | + error("invalid NAND device"); | |
133 | + fastboot_fail(response_str, "invalid NAND device"); | |
134 | + return; | |
135 | + } | |
136 | + | |
137 | + if (is_sparse_image(download_buffer)) { | |
138 | + struct fb_nand_sparse sparse_priv; | |
139 | + sparse_storage_t sparse; | |
140 | + | |
141 | + sparse_priv.nand = nand; | |
142 | + sparse_priv.part = part; | |
143 | + | |
144 | + sparse.block_sz = nand->writesize; | |
145 | + sparse.start = part->offset / sparse.block_sz; | |
146 | + sparse.size = part->size / sparse.block_sz; | |
147 | + sparse.name = part->name; | |
148 | + sparse.write = fb_nand_sparse_write; | |
149 | + | |
150 | + ret = store_sparse_image(&sparse, &sparse_priv, session_id, | |
151 | + download_buffer); | |
152 | + } else { | |
153 | + printf("Flashing raw image at offset 0x%llx\n", | |
154 | + part->offset); | |
155 | + | |
156 | + ret = _fb_nand_write(nand, part, download_buffer, part->offset, | |
157 | + download_bytes, NULL); | |
158 | + | |
159 | + printf("........ wrote %u bytes to '%s'\n", | |
160 | + download_bytes, part->name); | |
161 | + } | |
162 | + | |
163 | + if (ret) { | |
164 | + fastboot_fail(response_str, "error writing the image"); | |
165 | + return; | |
166 | + } | |
167 | + | |
168 | + fastboot_okay(response_str, ""); | |
169 | +} | |
170 | + | |
171 | +void fb_nand_erase(const char *partname, char *response) | |
172 | +{ | |
173 | + struct part_info *part; | |
174 | + nand_info_t *nand = NULL; | |
175 | + int ret; | |
176 | + | |
177 | + /* initialize the response buffer */ | |
178 | + response_str = response; | |
179 | + | |
180 | + ret = fb_nand_lookup(partname, response, &nand, &part); | |
181 | + if (ret) { | |
182 | + error("invalid NAND device"); | |
183 | + fastboot_fail(response_str, "invalid NAND device"); | |
184 | + return; | |
185 | + } | |
186 | + | |
187 | + ret = _fb_nand_erase(nand, part); | |
188 | + if (ret) { | |
189 | + error("failed erasing from device %s", nand->name); | |
190 | + fastboot_fail(response_str, "failed erasing from device"); | |
191 | + return; | |
192 | + } | |
193 | + | |
194 | + fastboot_okay(response_str, ""); | |
195 | +} |
drivers/usb/gadget/f_fastboot.c
... | ... | @@ -24,6 +24,9 @@ |
24 | 24 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV |
25 | 25 | #include <fb_mmc.h> |
26 | 26 | #endif |
27 | +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV | |
28 | +#include <fb_nand.h> | |
29 | +#endif | |
27 | 30 | |
28 | 31 | #define FASTBOOT_VERSION "0.4" |
29 | 32 | |
... | ... | @@ -569,6 +572,11 @@ |
569 | 572 | (void *)CONFIG_FASTBOOT_BUF_ADDR, |
570 | 573 | download_bytes, response); |
571 | 574 | #endif |
575 | +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV | |
576 | + fb_nand_flash_write(cmd, fastboot_flash_session_id, | |
577 | + (void *)CONFIG_FASTBOOT_BUF_ADDR, | |
578 | + download_bytes, response); | |
579 | +#endif | |
572 | 580 | fastboot_flash_session_id++; |
573 | 581 | fastboot_tx_write_str(response); |
574 | 582 | } |
... | ... | @@ -613,6 +621,9 @@ |
613 | 621 | |
614 | 622 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV |
615 | 623 | fb_mmc_erase(cmd, response); |
624 | +#endif | |
625 | +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV | |
626 | + fb_nand_erase(cmd, response); | |
616 | 627 | #endif |
617 | 628 | fastboot_tx_write_str(response); |
618 | 629 | } |
include/fb_nand.h
1 | +/* | |
2 | + * Copyright 2014 Broadcom Corporation. | |
3 | + * Copyright 2015 Free Electrons. | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +void fb_nand_flash_write(const char *cmd, unsigned int session_id, | |
9 | + void *download_buffer, unsigned int download_bytes, | |
10 | + char *response); | |
11 | +void fb_nand_erase(const char *cmd, char *response); |