blob: 6e474cdbbca14e10a8a0fbe484e2af25e397662e [file] [log] [blame]
David Hendricksee712472012-05-23 21:50:59 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2012 The Chromium OS Authors. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Google or the names of contributors or
18 * licensors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind.
22 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25 * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
26 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
27 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
28 * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
29 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
30 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
31 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
32 * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 */
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +080034
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include "flashchips.h"
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080040#include "fmap.h"
Louis Yung-Chieh Loc0505242012-08-09 23:11:32 +080041#include "gec_lock.h"
David Hendrickscf6e3a32012-08-01 16:13:02 -070042#include "gec_lpc_commands.h"
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +080043#include "programmer.h"
44#include "spi.h"
45#include "writeprotect.h"
46
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +080047/* FIXME: used for wp hacks */
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
52struct wp_data {
53 int enable;
54 unsigned int start;
55 unsigned int len;
56};
57static struct wp_data fake_wp;
58#define WP_STATE_HACK_FILENAME "/mnt/stateful_partition/flashrom_wp_state"
59
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080060/* 1 if we want the flashrom to call erase_and_write_flash() again. */
61static int need_2nd_pass = 0;
62
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +080063/* 1 if we want the flashrom to try jumping to new firmware after update. */
64static int try_latest_firmware = 0;
65
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080066/* The range of each firmware copy from the image file to update.
67 * But re-define the .flags as the valid flag to indicate the firmware is
68 * new or not (if flags = 1).
69 */
70static struct fmap_area fwcopy[4]; // [0] is not used.
71
72/* The names of enum lpc_current_image to match in FMAP area names. */
David Hendricksbf8c4dd2012-07-19 12:13:17 -070073static const char *sections[3] = {
74 "UNKNOWN SECTION", // EC_IMAGE_UNKNOWN -- never matches
75 "EC_RO",
76 "EC_RW",
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080077};
78
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +080079
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080080/* Given the range not able to update, mark the corresponding
81 * firmware as old.
82 */
83static void gec_invalidate_copy(unsigned int addr, unsigned int len)
84{
85 int i;
86
David Hendrickscf6e3a32012-08-01 16:13:02 -070087 for (i = EC_LPC_IMAGE_RO; i < ARRAY_SIZE(fwcopy); i++) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +080088 struct fmap_area *fw = &fwcopy[i];
89 if ((addr >= fw->offset && (addr < fw->offset + fw->size)) ||
90 (fw->offset >= addr && (fw->offset < addr + len))) {
91 msg_pdbg("Mark firmware [%s] as old.\n",
92 sections[i]);
93 fw->flags = 0; // mark as old
94 }
95 }
96}
97
98
David Hendrickscf6e3a32012-08-01 16:13:02 -070099/* Asks EC to jump to a firmware copy. If target is EC_LPC_IMAGE_UNKNOWN,
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800100 * then this functions picks a NEW firmware copy and jumps to it. Note that
101 * RO is preferred, then A, finally B.
102 *
103 * Returns 0 for success.
104 */
David Hendrickscf6e3a32012-08-01 16:13:02 -0700105static int gec_jump_copy(enum lpc_current_image target) {
106 struct lpc_params_reboot_ec p;
David Hendricks7cfbd022012-05-20 17:25:51 -0700107 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800108 int rc;
109
Louis Yung-Chieh Lobb128ba2012-05-04 22:57:44 +0800110 memset(&p, 0, sizeof(p));
David Hendrickscf6e3a32012-08-01 16:13:02 -0700111 p.target = target != EC_LPC_IMAGE_UNKNOWN ? target :
112 fwcopy[EC_LPC_IMAGE_RO].flags ? EC_LPC_IMAGE_RO :
113 fwcopy[EC_LPC_IMAGE_RW].flags ? EC_LPC_IMAGE_RW :
114 EC_LPC_IMAGE_UNKNOWN;
115 msg_pdbg("GEC is jumping to [%s]\n", sections[p.target]);
116 if (p.target == EC_LPC_IMAGE_UNKNOWN) return 1;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800117
David Hendrickscf6e3a32012-08-01 16:13:02 -0700118 rc = priv->ec_command(EC_LPC_COMMAND_REBOOT_EC,
David Hendricks7cfbd022012-05-20 17:25:51 -0700119 &p, sizeof(p), NULL, 0);
David Hendrickscf6e3a32012-08-01 16:13:02 -0700120 if (rc) {
121 msg_perr("GEC cannot jump to [%s]\n", sections[p.target]);
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800122 } else {
David Hendrickscf6e3a32012-08-01 16:13:02 -0700123 msg_pdbg("GEC has jumped to [%s]\n", sections[p.target]);
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800124 }
125
126 /* Sleep 1 sec to wait the EC re-init. */
127 usleep(1000000);
128
129 return rc;
130}
131
132
133/* Given an image, this function parses FMAP and recognize the firmware
134 * ranges.
135 */
136int gec_prepare(uint8_t *image, int size) {
David Hendricks7cfbd022012-05-20 17:25:51 -0700137 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800138 struct fmap *fmap;
139 int i, j;
140
Louis Yung-Chieh Lo0eaa0ca2012-05-29 15:28:58 +0800141 if (!(priv && priv->detected)) return 0;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800142
143 // Parse the fmap in the image file and cache the firmware ranges.
144 fmap = fmap_find_in_memory(image, size);
145 if (!fmap) return 0;
146
147 // Lookup RO/A/B sections in FMAP.
148 for (i = 0; i < fmap->nareas; i++) {
149 struct fmap_area *fa = &fmap->areas[i];
David Hendrickscf6e3a32012-08-01 16:13:02 -0700150 for (j = EC_LPC_IMAGE_RO; j < ARRAY_SIZE(sections); j++) {
David Hendricks5b06c882012-05-20 18:27:25 -0700151 if (!strcmp(sections[j], (const char *)fa->name)) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800152 msg_pdbg("Found '%s' in image.\n", fa->name);
153 memcpy(&fwcopy[j], fa, sizeof(*fa));
154 fwcopy[j].flags = 1; // mark as new
155 }
156 }
157 }
158
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +0800159 /* Warning: before update, we jump the EC to RO copy. If you want to
160 * change this behavior, please also check the gec_finish().
161 */
David Hendrickscf6e3a32012-08-01 16:13:02 -0700162 return gec_jump_copy(EC_LPC_IMAGE_RO);
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800163}
164
165
166/* Returns >0 if we need 2nd pass of erase_and_write_flash().
167 * <0 if we cannot jump to any firmware copy.
168 * ==0 if no more pass is needed.
169 *
170 * This function also jumps to new-updated firmware copy before return >0.
171 */
172int gec_need_2nd_pass(void) {
David Hendricks7cfbd022012-05-20 17:25:51 -0700173 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
174
Louis Yung-Chieh Lo0eaa0ca2012-05-29 15:28:58 +0800175 if (!(priv && priv->detected)) return 0;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800176
177 if (need_2nd_pass) {
David Hendrickscf6e3a32012-08-01 16:13:02 -0700178 if (gec_jump_copy(EC_LPC_IMAGE_UNKNOWN)) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800179 return -1;
180 }
181 }
182
183 return need_2nd_pass;
184}
185
186
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +0800187/* Returns 0 for success.
188 *
189 * Try latest firmware: B > A > RO
190 *
191 * This function assumes the EC jumps to RO at gec_prepare() so that
192 * the fwcopy[RO].flags is old (0) and A/B are new. Please also refine
193 * this code logic if you change the gec_prepare() behavior.
194 */
195int gec_finish(void) {
196 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
197
198 if (!(priv && priv->detected)) return 0;
199
200 if (try_latest_firmware) {
David Hendrickscf6e3a32012-08-01 16:13:02 -0700201 if (fwcopy[EC_LPC_IMAGE_RW].flags &&
202 gec_jump_copy(EC_LPC_IMAGE_RW) == 0) return 0;
203 return gec_jump_copy(EC_LPC_IMAGE_RO);
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +0800204 }
205
206 return 0;
207}
208
209
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800210int gec_read(struct flashchip *flash, uint8_t *readarr,
211 unsigned int blockaddr, unsigned int readcnt) {
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800212 int rc = 0;
David Hendrickscf6e3a32012-08-01 16:13:02 -0700213 struct lpc_params_flash_read p;
214 struct lpc_response_flash_read r;
David Hendricks7cfbd022012-05-20 17:25:51 -0700215 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
David Hendricksd6a0f662012-05-29 14:39:50 -0700216 int maxlen = opaque_programmer->max_data_read;
David Hendricks133083b2012-07-17 20:39:38 -0700217 int offset = 0, count;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800218
David Hendricks133083b2012-07-17 20:39:38 -0700219 while (offset < readcnt) {
220 count = min(maxlen, readcnt - offset);
221 p.offset = blockaddr + offset;
222 p.size = count;
David Hendrickscf6e3a32012-08-01 16:13:02 -0700223 rc = priv->ec_command(EC_LPC_COMMAND_FLASH_READ,
224 &p, sizeof(p), &r, count);
225 if (rc) {
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800226 msg_perr("GEC: Flash read error at offset 0x%x\n",
David Hendricks133083b2012-07-17 20:39:38 -0700227 blockaddr + offset);
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800228 return rc;
229 }
230
David Hendrickscf6e3a32012-08-01 16:13:02 -0700231 memcpy(readarr + offset, r.data, count);
David Hendricks133083b2012-07-17 20:39:38 -0700232 offset += count;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800233 }
234
235 return rc;
236}
237
238
David Hendricks7cfbd022012-05-20 17:25:51 -0700239int gec_block_erase(struct flashchip *flash,
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800240 unsigned int blockaddr,
241 unsigned int len) {
David Hendrickscf6e3a32012-08-01 16:13:02 -0700242 struct lpc_params_flash_erase erase;
David Hendricks7cfbd022012-05-20 17:25:51 -0700243 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800244 int rc;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800245
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800246 erase.offset = blockaddr;
247 erase.size = len;
David Hendrickscf6e3a32012-08-01 16:13:02 -0700248 rc = priv->ec_command(EC_LPC_COMMAND_FLASH_ERASE,
David Hendricks7cfbd022012-05-20 17:25:51 -0700249 &erase, sizeof(erase), NULL, 0);
David Hendrickscf6e3a32012-08-01 16:13:02 -0700250 if (rc == EC_LPC_RESULT_ACCESS_DENIED) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800251 // this is active image.
252 gec_invalidate_copy(blockaddr, len);
253 need_2nd_pass = 1;
254 return ACCESS_DENIED;
255 }
David Hendrickscf6e3a32012-08-01 16:13:02 -0700256 if (rc) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800257 msg_perr("GEC: Flash erase error at address 0x%x, rc=%d\n",
258 blockaddr, rc);
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800259 return rc;
260 }
261
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +0800262 try_latest_firmware = 1;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800263 return rc;
264}
265
266
267int gec_write(struct flashchip *flash, uint8_t *buf, unsigned int addr,
268 unsigned int nbytes) {
269 int i, rc = 0;
270 unsigned int written = 0;
David Hendrickscf6e3a32012-08-01 16:13:02 -0700271 struct lpc_params_flash_write p;
David Hendricks7cfbd022012-05-20 17:25:51 -0700272 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
David Hendricksd6a0f662012-05-29 14:39:50 -0700273 int maxlen = opaque_programmer->max_data_write;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800274
275 for (i = 0; i < nbytes; i += written) {
David Hendricksd6a0f662012-05-29 14:39:50 -0700276 written = min(nbytes - i, maxlen);
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800277 p.offset = addr + i;
278 p.size = written;
279 memcpy(p.data, &buf[i], written);
David Hendrickscf6e3a32012-08-01 16:13:02 -0700280 rc = priv->ec_command(EC_LPC_COMMAND_FLASH_WRITE,
David Hendricks7cfbd022012-05-20 17:25:51 -0700281 &p, sizeof(p), NULL, 0);
David Hendrickscf6e3a32012-08-01 16:13:02 -0700282 if (rc == EC_LPC_RESULT_ACCESS_DENIED) {
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +0800283 // this is active image.
284 gec_invalidate_copy(addr, nbytes);
285 need_2nd_pass = 1;
286 return ACCESS_DENIED;
287 }
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800288
David Hendrickscf6e3a32012-08-01 16:13:02 -0700289 if (rc) break;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800290 }
291
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +0800292 try_latest_firmware = 1;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800293 return rc;
294}
295
296
297static int gec_list_ranges(const struct flashchip *flash) {
298 msg_pinfo("You can specify any range:\n");
299 msg_pinfo(" from: 0x%06x, to: 0x%06x\n", 0, flash->total_size * 1024);
Randall Spangler6e160ef2012-07-18 09:36:25 -0700300 msg_pinfo(" unit: 0x%06x (%dKB)\n", 2048, 2);
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800301 return 0;
302}
303
304
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800305/* Temporary solution before the real EC WP is ready. This is a hack to
306 * avoid breaking factory procedure.
307 * This should be removed after crosbug.com/p/11320 and 11219 are fixed.
308 */
309static int load_fake_wp(void) {
310 int fd;
311
312 if ((fd = open(WP_STATE_HACK_FILENAME, O_RDONLY)) == -1)
313 goto read_err;
314
315 if (read(fd, &fake_wp, sizeof(fake_wp)) != sizeof(fake_wp))
316 goto read_err;
317
318 close(fd);
319 return 0;
320
321read_err:
322 memset(&fake_wp, 0 , sizeof(fake_wp));
323 return 0;
324}
325
326static int save_fake_wp(void) {
327 int fd;
328
329 if ((fd = open(WP_STATE_HACK_FILENAME,
330 O_CREAT | O_TRUNC | O_RDWR, 0644)) == -1)
331 return -1;
332
333 if (write(fd, &fake_wp, sizeof(fake_wp)) != sizeof(fake_wp))
334 return -1;
335
336 close(fd);
337 return 0;
338}
339
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800340static int gec_set_range(const struct flashchip *flash,
341 unsigned int start, unsigned int len) {
Randall Spangler6e160ef2012-07-18 09:36:25 -0700342 /* TODO: update to latest ec_commands.h and reimplement. */
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800343 int rc;
344
345 rc = system("crossystem wpsw_cur?1");
346 if (rc) /* change-able only when WP pin is de-asserted. */
347 return -1;
348 load_fake_wp();
349 fake_wp.start = start;
350 fake_wp.len = len;
351 return save_fake_wp();
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800352}
353
354
355static int gec_enable_writeprotect(const struct flashchip *flash) {
Randall Spangler6e160ef2012-07-18 09:36:25 -0700356 /* TODO: update to latest ec_commands.h and reimplement. */
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800357 load_fake_wp();
358 fake_wp.enable = 1;
359 return save_fake_wp();
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800360}
361
362
363static int gec_disable_writeprotect(const struct flashchip *flash) {
Randall Spangler6e160ef2012-07-18 09:36:25 -0700364 /* TODO: update to latest ec_commands.h and reimplement. */
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800365 int rc;
366
367 rc = system("crossystem wpsw_cur?1");
368 if (rc) /* change-able only when WP pin is de-asserted. */
369 return -1;
370 load_fake_wp();
371 fake_wp.enable = 0;
372 return save_fake_wp();
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800373}
374
375
376static int gec_wp_status(const struct flashchip *flash) {
Randall Spangler6e160ef2012-07-18 09:36:25 -0700377 /*
378 * TODO: update to latest ec_commands.h and reimplement. For now,
379 * just claim chip is unprotected.
380 */
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800381
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800382 load_fake_wp();
Randall Spangler6e160ef2012-07-18 09:36:25 -0700383 msg_pinfo("WP: status: 0x%02x\n", 0);
384 msg_pinfo("WP: status.srp0: %x\n", 0);
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800385 msg_pinfo("WP: write protect is %s.\n",
386 fake_wp.enable ? "enabled" : "disabled");
387 msg_pinfo("WP: write protect range: start=0x%08x, len=0x%08x\n",
388 fake_wp.start, fake_wp.len);
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800389
Louis Yung-Chieh Lo05b7a7b2012-08-06 19:10:39 +0800390 /* TODO: Fix scripts which rely on SPI-specific terminology. */
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800391 return 0;
392}
393
394
David Hendricks7cfbd022012-05-20 17:25:51 -0700395int gec_probe_size(struct flashchip *flash) {
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800396 int rc;
David Hendrickscf6e3a32012-08-01 16:13:02 -0700397 struct lpc_response_flash_info info;
David Hendricks7cfbd022012-05-20 17:25:51 -0700398 struct gec_priv *priv = (struct gec_priv *)opaque_programmer->data;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800399 struct block_eraser *eraser;
400 static struct wp wp = {
401 .list_ranges = gec_list_ranges,
402 .set_range = gec_set_range,
403 .enable = gec_enable_writeprotect,
404 .disable = gec_disable_writeprotect,
405 .wp_status = gec_wp_status,
406 };
407
David Hendrickscf6e3a32012-08-01 16:13:02 -0700408 rc = priv->ec_command(EC_LPC_COMMAND_FLASH_INFO,
David Hendricks7cfbd022012-05-20 17:25:51 -0700409 NULL, 0, &info, sizeof(info));
David Hendrickscf6e3a32012-08-01 16:13:02 -0700410 if (rc) return 0;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800411
412 flash->total_size = info.flash_size / 1024;
David Hendricks0d3fcb52012-07-08 18:37:43 -0700413 flash->page_size = 64;
Louis Yung-Chieh Loedb0cba2011-12-09 17:06:54 +0800414 flash->tested = TEST_OK_PREW;
415 eraser = &flash->block_erasers[0];
416 eraser->eraseblocks[0].size = info.erase_block_size;
417 eraser->eraseblocks[0].count = info.flash_size /
418 eraser->eraseblocks[0].size;
419 flash->wp = &wp;
420
421 return 1;
422};