Commit 2422d1ca authored by Sean Cross's avatar Sean Cross

Merge pull request #30 from pfalcon/flashrom-docs

Add instructions and patch to use "flashrom" tool to backup onboard flash.
parents 0faf0287 f345568b
......@@ -100,6 +100,8 @@ That is, send the following packet:
| 00 00 |
See ROM-BACKUP.txt for user-level instructions how to backup/restore
FlashROM of your device.
Licensing
---------
......
Fernly doesn't require changing a firmware stored in FlashROM of
your device - it runs completely from RAM. You may still want
to backup the original firmware for various reasons. Following
gives a walkthru how to do this.
1. Check out the latest flashrom HEAD:
svn co http://code.coreboot.org/svn/flashrom/trunk flashrom
Using latest HEAD is recommended, as it may have more chip definitions,
and there's less chance it won't recognize your FlashROM.
2. Apply flashrom-fernvale.patch from fernly:
patch -p0 <flashrom-fernvale.patch
3. You may need to install libusb-0.1 development headers to build it
(0.1 is "old" libusb, many projects use modern 1.0 version). For ubuntu:
apt-get install libusb-dev
4. Build with:
make WARNERROR=no
5. Start fernly without "-s" (shell) switch:
./build/fernly-usb-loader -w /dev/ttyUSB0 ./build/usb-loader.bin ./build/firmware.bin
6. Run flashrom to dump device FlashROM to a file:
./flashrom --programmer fernvale_spi:dev=/dev/ttyUSB0 --read flash.dat
If you're unlucky, it may report that it cannot recognize your device has
a ROM it can't recognize. If so, follow flashrom documentation on what to do.
Otherwise, expect that reading 16MB of flash to take up to 10 minutes -
without any progress indicator or something.
7. Refer to flashrom documentation for writing (generally it's as simple
as giving --write option instead of --read).
This patch adds "fernvale_spi" "programmer" for "flashrom" utility
http://flashrom.org/ . It allows read or program FlashROM on a
Mediatek MT6260 device using "fernly" bootloader
https://github.com/xobs/fernly .
Author: Sean Cross <xobs@kosagi.com>
Index: Makefile
===================================================================
--- Makefile (revision 1897)
+++ Makefile (working copy)
@@ -272,6 +272,11 @@
else
override CONFIG_BUSPIRATE_SPI = no
endif
+ifeq ($(CONFIG_FERNVALE_SPI), yes)
+UNSUPPORTED_FEATURES += CONFIG_FERNVALE_SPI=yes
+else
+override CONFIG_FERNVALE_SPI = no
+endif
ifeq ($(CONFIG_SERPROG), yes)
UNSUPPORTED_FEATURES += CONFIG_SERPROG=yes
else
@@ -469,6 +474,9 @@
# Always enable Bus Pirate SPI for now.
CONFIG_BUSPIRATE_SPI ?= yes
+# Always enable Fernvale SPI, too
+CONFIG_FERNVALE_SPI ?= yes
+
# Disable Dediprog SF100 until support is complete and tested.
CONFIG_DEDIPROG ?= no
@@ -694,6 +702,12 @@
NEED_SERIAL := yes
endif
+ifeq ($(CONFIG_FERNVALE_SPI), yes)
+FEATURE_CFLAGS += -D'CONFIG_FERNVALE_SPI=1'
+PROGRAMMER_OBJS += fernvale_spi.o
+NEED_SERIAL := yes
+endif
+
ifeq ($(CONFIG_DEDIPROG), yes)
FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1'
PROGRAMMER_OBJS += dediprog.o
Index: fernvale_spi.c
===================================================================
--- fernvale_spi.c (revision 0)
+++ fernvale_spi.c (working copy)
@@ -0,0 +1,238 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "flash.h"
+#include "programmer.h"
+#include "spi.h"
+
+#define DEFAULT_DEV "/dev/fernvale"
+#define BAUDRATE B921600
+
+static struct {
+ int fd;
+} fernvale_data;
+
+static int fernvale_spi_send_command(struct flashctx *flash,
+ unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr,
+ unsigned char *readarr);
+
+static const struct spi_master spi_master_fernvale = {
+ .type = SPI_CONTROLLER_FERNVALE,
+ .max_data_read = 128,
+ .max_data_write = 128,
+ .command = fernvale_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+ .write_aai = default_spi_write_aai,
+};
+
+static int fernvale_spi_shutdown(void *data)
+{
+ const char cmd[] = { 0, 0 };
+
+ write(fernvale_data.fd, cmd, sizeof(cmd));
+
+ return 0;
+}
+
+static int fernvale_spi_setserial(int serfd)
+{
+ int ret;
+ struct termios t;
+
+ ret = tcgetattr(serfd, &t);
+ if (-1 == ret) {
+ perror("Failed to get attributes");
+ exit(1);
+ }
+ cfsetispeed(&t, BAUDRATE);
+ cfsetospeed(&t, BAUDRATE);
+ cfmakeraw(&t);
+ ret = tcsetattr(serfd, TCSANOW, &t);
+ if (-1 == ret) {
+ perror("Failed to set attributes");
+ exit(1);
+ }
+
+ return 0;
+}
+
+int fernvale_spi_init(void)
+{
+ struct spi_master mst = spi_master_fernvale;
+ char *dev;
+
+ dev = extract_programmer_param("dev");
+ if (dev && !strlen(dev)) {
+ free(dev);
+ dev = NULL;
+ }
+ if (!dev)
+ dev = DEFAULT_DEV;
+
+ fernvale_data.fd = open(dev, O_RDWR);
+ if (fernvale_data.fd == -1) {
+ msg_perr("Unable to open serial device. "
+ "Use flashrom -p fernvale_spi:dev=/dev/ttyUSB0\n");
+ return 1;
+ }
+
+ fernvale_spi_setserial(fernvale_data.fd);
+
+ const char cmd[] = "spi flashrom\n";
+ char readback;
+ int ready_tries = 0;
+ write(fernvale_data.fd, cmd, strlen(cmd));
+
+ /* Look for "Ready" signal */
+ do {
+ read(fernvale_data.fd, &readback, sizeof(readback));
+ ready_tries++;
+ } while (readback != 0x05);
+ msg_gdbg("Found 'ready' signal after %d bytes\n", ready_tries);
+
+ mst.data = &fernvale_data;
+ register_spi_master(&mst);
+ register_shutdown(fernvale_spi_shutdown, NULL);
+
+ return 0;
+}
+
+static int write_full(int fd, const void *bfr, int size)
+{
+ int ret;
+ int left = size;
+
+ while (left > 0) {
+ ret = write(fd, bfr, left);
+ if (ret == -1) {
+ if (errno == EAGAIN)
+ continue;
+ return ret;
+ }
+
+ /* FD closed */
+ if (!ret)
+ return -1;
+
+ left -= ret;
+ bfr += ret;
+ }
+ return size;
+}
+
+static int read_full(int fd, void *bfr, int size)
+{
+ int ret;
+ int left = size;
+
+ msg_gdbg(" Reading %d bytes:", size);
+ while (left > 0) {
+ ret = read(fd, bfr, 1);
+ if (ret == -1) {
+ if (errno == EAGAIN)
+ continue;
+ return ret;
+ }
+ msg_gdbg(" 0x%02x:", *((uint8_t *)bfr));
+
+ /* FD closed */
+ if (!ret)
+ return -1;
+
+ left -= ret;
+ bfr += ret;
+ }
+ return size;
+}
+
+static int fernvale_spi_send_command(struct flashctx *flash,
+ unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr,
+ unsigned char *readarr)
+{
+ uint8_t out_bytes = writecnt;
+ uint8_t in_bytes = readcnt;
+ int ret;
+ int fd = fernvale_data.fd;
+ int i;
+#if 1
+ ret = write_full(fd, &out_bytes, sizeof(out_bytes));
+ if (ret != sizeof(out_bytes))
+ msg_perr("0: Wanted to write %d bytes, but got %d\n",
+ (int)sizeof(out_bytes), ret);
+
+ ret = write_full(fd, &in_bytes, sizeof(in_bytes));
+ if (ret != sizeof(in_bytes))
+ msg_perr("1: Wanted to write %d bytes, but got %d\n",
+ (int)sizeof(in_bytes), ret);
+
+ ret = write_full(fd, writearr, out_bytes);
+ if (ret != out_bytes)
+ msg_perr("0: Wanted to write %d bytes, but got %d\n",
+ out_bytes, ret);
+
+ msg_gdbg(" Wrote %d bytes:", out_bytes);
+ for (i = 0; i < out_bytes; i++)
+ msg_gdbg(" %02x", writearr[i]);
+ msg_gdbg(" ");
+#else
+ uint8_t bfr[writecnt + 2];
+
+ bfr[0] = out_bytes;
+ bfr[1] = in_bytes;
+ memcpy(&bfr[2], writearr, out_bytes);
+
+ ret = write_full(fd, bfr, sizeof(bfr));
+ if (ret != sizeof(bfr))
+ msg_perr("0: Wanted to write %d bytes, but got %d\n",
+ sizeof(bfr), ret);
+
+ msg_gdbg(" Wrote %d bytes:", sizeof(bfr));
+ for (i = 0; i < sizeof(bfr); i++)
+ msg_gdbg(" %02x", bfr[i]);
+ msg_gdbg(" ");
+#endif
+
+ ret = read_full(fd, readarr, in_bytes);
+ if (ret != in_bytes)
+ msg_perr("3: Wanted to read %d bytes, but got %d\n",
+ in_bytes, ret);
+
+ msg_gdbg(" Read %d bytes:", in_bytes);
+ for (i = 0; i < in_bytes; i++)
+ msg_gdbg(" %02x", readarr[i]);
+ msg_gdbg(" ");
+
+ msg_gdbg("\n");
+
+ return 0;
+}
Index: flashrom.c
===================================================================
--- flashrom.c (revision 1897)
+++ flashrom.c (working copy)
@@ -231,6 +231,19 @@
},
#endif
+#if CONFIG_FERNVALE_SPI == 1
+ {
+ .name = "fernvale_spi",
+ .type = OTHER,
+ /* FIXME */
+ .devs.note = "Kosagi Fernvale\n",
+ .init = fernvale_spi_init,
+ .map_flash_region = fallback_map,
+ .unmap_flash_region = fallback_unmap,
+ .delay = internal_delay,
+ },
+#endif
+
#if CONFIG_DEDIPROG == 1
{
.name = "dediprog",
Index: programmer.h
===================================================================
--- programmer.h (revision 1897)
+++ programmer.h (working copy)
@@ -69,6 +69,9 @@
#if CONFIG_BUSPIRATE_SPI == 1
PROGRAMMER_BUSPIRATE_SPI,
#endif
+#if CONFIG_FERNVALE_SPI == 1
+ PROGRAMMER_FERNVALE_SPI,
+#endif
#if CONFIG_DEDIPROG == 1
PROGRAMMER_DEDIPROG,
#endif
@@ -506,6 +509,11 @@
int buspirate_spi_init(void);
#endif
+/* fernvale_spi.c */
+#if CONFIG_FERNVALE_SPI == 1
+int fernvale_spi_init(void);
+#endif
+
/* linux_spi.c */
#if CONFIG_LINUX_SPI == 1
int linux_spi_init(void);
@@ -554,6 +562,9 @@
#if CONFIG_BUSPIRATE_SPI == 1
SPI_CONTROLLER_BUSPIRATE,
#endif
+#if CONFIG_FERNVALE_SPI == 1
+ SPI_CONTROLLER_FERNVALE,
+#endif
#if CONFIG_DEDIPROG == 1
SPI_CONTROLLER_DEDIPROG,
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment