Blame view

common/fb_nand.c 4.98 KB
bf8940d35   Maxime Ripard   fastboot: Impleme...
1
2
3
4
5
6
7
8
9
  /*
   * Copyright 2014 Broadcom Corporation.
   * Copyright 2015 Free Electrons.
   *
   * SPDX-License-Identifier:	GPL-2.0+
   */
  
  #include <config.h>
  #include <common.h>
bf8940d35   Maxime Ripard   fastboot: Impleme...
10
  #include <fastboot.h>
3d4ef38de   Maxime Ripard   sparse: Rename th...
11
  #include <image-sparse.h>
bf8940d35   Maxime Ripard   fastboot: Impleme...
12
13
14
15
  
  #include <linux/mtd/mtd.h>
  #include <jffs2/jffs2.h>
  #include <nand.h>
bf8940d35   Maxime Ripard   fastboot: Impleme...
16
  struct fb_nand_sparse {
cc0f08cd3   Steve Rae   fastboot: sparse:...
17
  	struct mtd_info		*mtd;
bf8940d35   Maxime Ripard   fastboot: Impleme...
18
19
  	struct part_info	*part;
  };
6fb77c48e   Maxime Ripard   fastboot: nand: A...
20
21
22
23
24
25
26
27
28
  __weak int board_fastboot_erase_partition_setup(char *name)
  {
  	return 0;
  }
  
  __weak int board_fastboot_write_partition_setup(char *name)
  {
  	return 0;
  }
9bc34799c   Steve Rae   fastboot: sparse:...
29
  static int fb_nand_lookup(const char *partname,
61717571f   Sergey Kubushyn   common: fb_nand: ...
30
  			  struct mtd_info **mtd,
bf8940d35   Maxime Ripard   fastboot: Impleme...
31
32
33
34
35
36
37
38
  			  struct part_info **part)
  {
  	struct mtd_device *dev;
  	int ret;
  	u8 pnum;
  
  	ret = mtdparts_init();
  	if (ret) {
9b643e312   Masahiro Yamada   treewide: replace...
39
40
  		pr_err("Cannot initialize MTD partitions
  ");
9bc34799c   Steve Rae   fastboot: sparse:...
41
  		fastboot_fail("cannot init mtdparts");
bf8940d35   Maxime Ripard   fastboot: Impleme...
42
43
44
45
46
  		return ret;
  	}
  
  	ret = find_dev_and_part(partname, &dev, &pnum, part);
  	if (ret) {
9b643e312   Masahiro Yamada   treewide: replace...
47
  		pr_err("cannot find partition: '%s'", partname);
9bc34799c   Steve Rae   fastboot: sparse:...
48
  		fastboot_fail("cannot find partition");
bf8940d35   Maxime Ripard   fastboot: Impleme...
49
50
51
52
  		return ret;
  	}
  
  	if (dev->id->type != MTD_DEV_TYPE_NAND) {
9b643e312   Masahiro Yamada   treewide: replace...
53
  		pr_err("partition '%s' is not stored on a NAND device",
bf8940d35   Maxime Ripard   fastboot: Impleme...
54
  		      partname);
9bc34799c   Steve Rae   fastboot: sparse:...
55
  		fastboot_fail("not a NAND device");
bf8940d35   Maxime Ripard   fastboot: Impleme...
56
57
  		return -EINVAL;
  	}
edba8cc4f   Grygorii Strashko   common: use get_n...
58
  	*mtd = get_nand_dev_by_index(dev->id->num);
bf8940d35   Maxime Ripard   fastboot: Impleme...
59
60
61
  
  	return 0;
  }
151c06ec6   Scott Wood   mtd: nand: Remove...
62
  static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part)
bf8940d35   Maxime Ripard   fastboot: Impleme...
63
64
65
66
67
68
69
70
71
72
73
74
  {
  	nand_erase_options_t opts;
  	int ret;
  
  	memset(&opts, 0, sizeof(opts));
  	opts.offset = part->offset;
  	opts.length = part->size;
  	opts.quiet = 1;
  
  	printf("Erasing blocks 0x%llx to 0x%llx
  ",
  	       part->offset, part->offset + part->size);
151c06ec6   Scott Wood   mtd: nand: Remove...
75
  	ret = nand_erase_opts(mtd, &opts);
bf8940d35   Maxime Ripard   fastboot: Impleme...
76
77
78
79
80
81
82
83
84
  	if (ret)
  		return ret;
  
  	printf("........ erased 0x%llx bytes from '%s'
  ",
  	       part->size, part->name);
  
  	return 0;
  }
151c06ec6   Scott Wood   mtd: nand: Remove...
85
  static int _fb_nand_write(struct mtd_info *mtd, struct part_info *part,
bf8940d35   Maxime Ripard   fastboot: Impleme...
86
87
88
89
90
91
92
93
  			  void *buffer, unsigned int offset,
  			  unsigned int length, size_t *written)
  {
  	int flags = WITH_WR_VERIFY;
  
  #ifdef CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS
  	flags |= WITH_DROP_FFS;
  #endif
151c06ec6   Scott Wood   mtd: nand: Remove...
94
  	return nand_write_skip_bad(mtd, offset, &length, written,
bf8940d35   Maxime Ripard   fastboot: Impleme...
95
96
97
  				   part->size - (offset - part->offset),
  				   buffer, flags);
  }
cc0f08cd3   Steve Rae   fastboot: sparse:...
98
99
  static lbaint_t fb_nand_sparse_write(struct sparse_storage *info,
  		lbaint_t blk, lbaint_t blkcnt, const void *buffer)
bf8940d35   Maxime Ripard   fastboot: Impleme...
100
  {
cc0f08cd3   Steve Rae   fastboot: sparse:...
101
  	struct fb_nand_sparse *sparse = info->priv;
bf8940d35   Maxime Ripard   fastboot: Impleme...
102
103
  	size_t written;
  	int ret;
cc0f08cd3   Steve Rae   fastboot: sparse:...
104
105
106
  	ret = _fb_nand_write(sparse->mtd, sparse->part, (void *)buffer,
  			     blk * info->blksz,
  			     blkcnt * info->blksz, &written);
bf8940d35   Maxime Ripard   fastboot: Impleme...
107
108
109
110
111
  	if (ret < 0) {
  		printf("Failed to write sparse chunk
  ");
  		return ret;
  	}
cc0f08cd3   Steve Rae   fastboot: sparse:...
112
113
114
115
116
117
118
  /* TODO - verify that the value "written" includes the "bad-blocks" ... */
  
  	/*
  	 * the return value must be 'blkcnt' ("good-blocks") plus the
  	 * number of "bad-blocks" encountered within this space...
  	 */
  	return written / info->blksz;
bf8940d35   Maxime Ripard   fastboot: Impleme...
119
  }
2c7240468   Steve Rae   fastboot: sparse:...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  static lbaint_t fb_nand_sparse_reserve(struct sparse_storage *info,
  		lbaint_t blk, lbaint_t blkcnt)
  {
  	int bad_blocks = 0;
  
  /*
   * TODO - implement a function to determine the total number
   * of blocks which must be used in order to reserve the specified
   * number ("blkcnt") of "good-blocks", starting at "blk"...
   * ( possibly something like the "check_skip_len()" function )
   */
  
  	/*
  	 * the return value must be 'blkcnt' ("good-blocks") plus the
  	 * number of "bad-blocks" encountered within this space...
  	 */
  	return blkcnt + bad_blocks;
  }
cc0f08cd3   Steve Rae   fastboot: sparse:...
138
  void fb_nand_flash_write(const char *cmd, void *download_buffer,
9bc34799c   Steve Rae   fastboot: sparse:...
139
  			 unsigned int download_bytes)
bf8940d35   Maxime Ripard   fastboot: Impleme...
140
141
  {
  	struct part_info *part;
151c06ec6   Scott Wood   mtd: nand: Remove...
142
  	struct mtd_info *mtd = NULL;
bf8940d35   Maxime Ripard   fastboot: Impleme...
143
  	int ret;
9bc34799c   Steve Rae   fastboot: sparse:...
144
  	ret = fb_nand_lookup(cmd, &mtd, &part);
bf8940d35   Maxime Ripard   fastboot: Impleme...
145
  	if (ret) {
9b643e312   Masahiro Yamada   treewide: replace...
146
  		pr_err("invalid NAND device");
9bc34799c   Steve Rae   fastboot: sparse:...
147
  		fastboot_fail("invalid NAND device");
bf8940d35   Maxime Ripard   fastboot: Impleme...
148
149
  		return;
  	}
6fb77c48e   Maxime Ripard   fastboot: nand: A...
150
151
152
  	ret = board_fastboot_write_partition_setup(part->name);
  	if (ret)
  		return;
bf8940d35   Maxime Ripard   fastboot: Impleme...
153
154
  	if (is_sparse_image(download_buffer)) {
  		struct fb_nand_sparse sparse_priv;
cc0f08cd3   Steve Rae   fastboot: sparse:...
155
  		struct sparse_storage sparse;
bf8940d35   Maxime Ripard   fastboot: Impleme...
156

cc0f08cd3   Steve Rae   fastboot: sparse:...
157
  		sparse_priv.mtd = mtd;
bf8940d35   Maxime Ripard   fastboot: Impleme...
158
  		sparse_priv.part = part;
cc0f08cd3   Steve Rae   fastboot: sparse:...
159
160
161
  		sparse.blksz = mtd->writesize;
  		sparse.start = part->offset / sparse.blksz;
  		sparse.size = part->size / sparse.blksz;
bf8940d35   Maxime Ripard   fastboot: Impleme...
162
  		sparse.write = fb_nand_sparse_write;
2c7240468   Steve Rae   fastboot: sparse:...
163
  		sparse.reserve = fb_nand_sparse_reserve;
bf8940d35   Maxime Ripard   fastboot: Impleme...
164

cc0f08cd3   Steve Rae   fastboot: sparse:...
165
166
167
168
169
170
  		printf("Flashing sparse image at offset " LBAFU "
  ",
  		       sparse.start);
  
  		sparse.priv = &sparse_priv;
  		write_sparse_image(&sparse, cmd, download_buffer,
9bc34799c   Steve Rae   fastboot: sparse:...
171
  				   download_bytes);
bf8940d35   Maxime Ripard   fastboot: Impleme...
172
173
174
175
  	} else {
  		printf("Flashing raw image at offset 0x%llx
  ",
  		       part->offset);
151c06ec6   Scott Wood   mtd: nand: Remove...
176
  		ret = _fb_nand_write(mtd, part, download_buffer, part->offset,
bf8940d35   Maxime Ripard   fastboot: Impleme...
177
178
179
180
181
182
183
184
  				     download_bytes, NULL);
  
  		printf("........ wrote %u bytes to '%s'
  ",
  		       download_bytes, part->name);
  	}
  
  	if (ret) {
9bc34799c   Steve Rae   fastboot: sparse:...
185
  		fastboot_fail("error writing the image");
bf8940d35   Maxime Ripard   fastboot: Impleme...
186
187
  		return;
  	}
9bc34799c   Steve Rae   fastboot: sparse:...
188
  	fastboot_okay("");
bf8940d35   Maxime Ripard   fastboot: Impleme...
189
  }
9bc34799c   Steve Rae   fastboot: sparse:...
190
  void fb_nand_erase(const char *cmd)
bf8940d35   Maxime Ripard   fastboot: Impleme...
191
192
  {
  	struct part_info *part;
151c06ec6   Scott Wood   mtd: nand: Remove...
193
  	struct mtd_info *mtd = NULL;
bf8940d35   Maxime Ripard   fastboot: Impleme...
194
  	int ret;
9bc34799c   Steve Rae   fastboot: sparse:...
195
  	ret = fb_nand_lookup(cmd, &mtd, &part);
bf8940d35   Maxime Ripard   fastboot: Impleme...
196
  	if (ret) {
9b643e312   Masahiro Yamada   treewide: replace...
197
  		pr_err("invalid NAND device");
9bc34799c   Steve Rae   fastboot: sparse:...
198
  		fastboot_fail("invalid NAND device");
bf8940d35   Maxime Ripard   fastboot: Impleme...
199
200
  		return;
  	}
6fb77c48e   Maxime Ripard   fastboot: nand: A...
201
202
203
  	ret = board_fastboot_erase_partition_setup(part->name);
  	if (ret)
  		return;
151c06ec6   Scott Wood   mtd: nand: Remove...
204
  	ret = _fb_nand_erase(mtd, part);
bf8940d35   Maxime Ripard   fastboot: Impleme...
205
  	if (ret) {
9b643e312   Masahiro Yamada   treewide: replace...
206
  		pr_err("failed erasing from device %s", mtd->name);
9bc34799c   Steve Rae   fastboot: sparse:...
207
  		fastboot_fail("failed erasing from device");
bf8940d35   Maxime Ripard   fastboot: Impleme...
208
209
  		return;
  	}
9bc34799c   Steve Rae   fastboot: sparse:...
210
  	fastboot_okay("");
bf8940d35   Maxime Ripard   fastboot: Impleme...
211
  }