@@ -696,6 +696,11 @@
# Disable J-Link for now.
CONFIG_JLINK_SPI ?= no
+# Enable VIA VL805 programmer for now.
+CONFIG_VL805 ?= yes
+
+#PLACEHOLDER_NEWPROG_DEFAULTCONFIG
+
# Disable wiki printing by default. It is only useful if you have wiki access.
CONFIG_PRINT_WIKI ?= no
@@ -759,7 +764,9 @@
ifeq ($(CONFIG_OGP_SPI), yes)
override CONFIG_BITBANG_SPI = yes
else
+#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG1
CONFIG_BITBANG_SPI ?= no
+#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG2
endif
endif
endif
@@ -996,6 +1003,14 @@
PROGRAMMER_OBJS += mstarddc_spi.o
endif
+ifeq ($(CONFIG_VL805), yes)
+FEATURE_CFLAGS += -D'CONFIG_VL805=1'
+PROGRAMMER_OBJS += vl805.o
+NEED_PCI := yes
+endif
+
+#PLACEHOLDER_NEWPROG_COMPILERULE
+
ifeq ($(CONFIG_CH341A_SPI), yes)
FEATURE_CFLAGS += -D'CONFIG_CH341A_SPI=1'
PROGRAMMER_OBJS += ch341a_spi.o
@@ -142,7 +142,7 @@
if (rget_io_perms())
return 1;
- dev = pcidev_init(ata_via, PCI_ROM_ADDRESS); /* Acutally no BAR setup needed at all. */
+ dev = pcidev_init(ata_via, PCI_ROM_ADDRESS); /* Actually no BAR setup needed at all. */
if (!dev)
return 1;
@@ -0,0 +1,419 @@
+#!/bin/bash
+# flashrom programmer driver skeleton builder.
+# Copyright 2012,2020 Carl-Daniel Hailfinger
+# Licensed under the GNU GPL v2
+# The license of the generated programmer driver is unrelated to the licsense
+# of this script and can be specified below.
+
+# Fill in all info in the block below, and don't touch anything else.
+# The data provided here is just an example.
+# Name of the programmer. Needs to be an all-lowercase valid C identifier.
+PROGRAMMERNAME=vl805
+# Short description of the programmer. Please do not use / inside the name, it will break the sed expressions.
+PROGRAMMERDESCR="VIA VL805 programmer"
+# Name of the programmer manufacturer.
+PROGRAMMERMANUF="VIA"
+# Website for the programmer.
+PROGRAMMERURL="http://www.via.com/"
+# Fill in your name here.
+AUTHORNAME="Carl-Daniel Hailfinger"
+# License version of the new programmer driver: 2 or 2+ (for 2+later)
+LICENSE_GPL=2
+# Does the programmer need a map/unmap function?
+HAVE_MAP=no
+# Does the programmer have its own delay function?
+HAVE_DELAY=no
+# Does the programmer need some sort of direct hardware access?
+NEED_PCI=yes
+# Does the programmer need some sort of serial port access?
+NEED_SERIAL=no
+# Is the programmer a PCI device, USB device, or something else?
+# You have to specify exactly one of PCI, USB, OTHER
+DEVICETYPE=PCI
+# Note: Usually a programmer only has one of NEED_PARLPCFWH, NEED_SPI or NEED_SPI_BITBANG set to yes.
+# Does the programmer use Parallel/LPC/FWH functionality?
+NEED_PARLPCFWH=no
+# Which of PARALLEL/LPC/FWH buses does the programer use? FIXME: Explain how to handle multiple buses.
+BUS_PARLPCFWH=none
+# Does the programmer use SPI functionality without bitbanging? FIXME: Check if a SPI bitbanging driver with NEED_SPI=no generates useful code.
+NEED_SPI=yes
+# Does the programmer use the bitbanging SPI infrastructure?
+NEED_SPI_BITBANG=no
+
+# No user serviceable parts below.
+unset LANG
+unset LANGUAGE
+unset LC_COLLATE
+if test $LICENSE_GPL = 2; then
+ GPLV3EITHER=
+ GPLV3OR=
+elif test $LICENSE_GPL = 2+; then
+ GPLV3EITHER="either"
+ GPLV3OR="\n * (at your option) any later version"
+else
+ echo "Specified license can not be handled automatically"
+ exit 1
+fi
+if test $HAVE_MAP = yes; then MAPNAME=$PROGRAMMERNAME; else MAPNAME=fallback; fi
+if test $HAVE_DELAY = yes; then DELAYNAME=$PROGRAMMERNAME; else DELAYNAME=internal; fi
+PROGRAMMERNAMECAPS=$(echo -n $PROGRAMMERNAME|tr "[[:lower:]]" "[[:upper:]]")
+CONFIGNAME=CONFIG_$PROGRAMMERNAMECAPS
+ENUMNAME=PROGRAMMER_$PROGRAMMERNAMECAPS
+if test $NEED_PCI = yes; then NEEDS="NEED_PCI := yes\n"; fi
+if test $NEED_SERIAL = yes; then NEEDS+="NEED_SERIAL := yes\n"; fi
+
+sed "s-^//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY-\
+#if ${CONFIGNAME} == 1\n\
+ {\n\
+ .name = \"${PROGRAMMERNAME}\",\n\
+\0-" flashrom.c >flashrom.c.mine
+if test $DEVICETYPE = OTHER; then
+sed "s-^//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY-\
+ .type = OTHER,\n\
+ .devs.note = \"Textual list of usable devices\\\\n\",\n\
+\0-" flashrom.c.mine >flashrom.c.mine1
+mv flashrom.c.mine1 flashrom.c.mine
+else
+sed "s-^//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY-\
+ .type = ${DEVICETYPE},\n\
+ .devs.dev = devs_${PROGRAMMERNAME},\n\
+\0-" flashrom.c.mine >flashrom.c.mine1
+mv flashrom.c.mine1 flashrom.c.mine
+fi
+sed "s-^//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY-\
+ .init = ${PROGRAMMERNAME}_init,\n\
+ .map_flash_region = ${MAPNAME}_map,\n\
+ .unmap_flash_region = ${MAPNAME}_unmap,\n\
+ .delay = ${DELAYNAME}_delay,\n\
+ },\n\
+#endif\n\
+\n\0-" flashrom.c.mine >flashrom.c.mine1
+mv flashrom.c.mine1 flashrom.c.mine
+
+sed -e "s/^#PLACEHOLDER_NEWPROG_DEFAULTCONFIG/\
+# Enable ${PROGRAMMERDESCR} for now.\n\
+${CONFIGNAME} ?= yes\n\
+\n\0/" \
+-e "s/^#PLACEHOLDER_NEWPROG_COMPILERULE/\
+ifeq (\$(${CONFIGNAME}), yes)\n\
+FEATURE_CFLAGS += -D'${CONFIGNAME}=1'\n\
+PROGRAMMER_OBJS += ${PROGRAMMERNAME}.o\n\
+${NEEDS}\
+endif\n\
+\n\0/" Makefile >Makefile.mine
+
+if test $NEED_SPI_BITBANG = yes; then
+sed -e "s/^#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG1/\
+ifeq (\$(${CONFIGNAME}), yes)\n\
+override CONFIG_BITBANG_SPI = yes\n\
+else\n\
+\0/" \
+-e "s/^#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG2/\
+\0\n\
+endif/;" Makefile.mine >Makefile.mine1
+mv Makefile.mine1 Makefile.mine
+fi
+
+sed -e "s-^//PLACEHOLDER_NEWPROG_PROGRAMMER_ENUM-\
+#if ${CONFIGNAME} == 1\n\
+ ${ENUMNAME},\n\
+#endif\n\
+\0-" \
+-e "s-^//PLACEHOLDER_NEWPROG_PUBLICFUNCTIONS-\
+/* ${PROGRAMMERNAME}.c */\n\
+#if ${CONFIGNAME} == 1\n\
+int ${PROGRAMMERNAME}_init(void);\n\
+\0-" programmer.h >programmer.h.mine
+
+if test $DEVICETYPE = PCI -o $DEVICETYPE = USB; then
+sed -e "s-^//PLACEHOLDER_NEWPROG_PUBLICFUNCTIONS-\
+extern const struct dev_entry devs_${PROGRAMMERNAME}[];\n\
+\n\0-" programmer.h.mine >programmer.h.mine1
+mv programmer.h.mine1 programmer.h.mine
+fi
+
+sed -e "s-^//PLACEHOLDER_NEWPROG_PUBLICFUNCTIONS-\
+#endif\n\
+\n\0-" programmer.h.mine >programmer.h.mine1
+mv programmer.h.mine1 programmer.h.mine
+
+if test $NEED_SPI_BITBANG = yes; then
+sed -e "s-//PLACEHOLDER_NEWPROG_SELECT_SPI_BITBANG\$-\
+|| ${CONFIGNAME} == 1 \0-" programmer.h.mine >programmer.h.mine1
+mv programmer.h.mine1 programmer.h.mine
+fi
+
+# No idea if roff supports hidden comments. Hook up to hopefully unchanged sequences.
+sed -e "s/.*PLACEHOLDER_NEWPROG_MAN_SHORTDESCRIPTION/\
+.BR \"* ${PROGRAMMERNAME}\" \" (${PROGRAMMERDESCR})\"\n\
+.sp\n\
+\0/" \
+-e "s/.*PLACEHOLDER_NEWPROG_MAN_LONGDESCRIPTION/\
+.SS\n\
+.BR \"${PROGRAMMERNAME} \" programmer\n\
+Please describe the programmer parameters here.\n\
+\0/" \
+-e "s/.*PLACEHOLDER_NEWPROG_MAN_REQUIREMENTS/\
+.B ${PROGRAMMERNAME}\n\
+Please describe the programmer requirements here.\n\
+.sp\n\
+\0/" flashrom.8.tmpl > flashrom.8.tmpl.mine
+
+cat >$PROGRAMMERNAME.c.mine <<EOF
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) $(date +%Y) ${AUTHORNAME}
+ *
+ * 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; ${GPLV3EITHER}version 2 of the License${GPLV3OR}.
+ *
+ * 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
+ */
+
+/* Driver for the ${PROGRAMMERDESCR} hardware by ${PROGRAMMERMANUF}.
+ * See ${PROGRAMMERURL} for more info.
+ */
+
+#include "flash.h"
+#include "programmer.h"
+
+EOF
+
+if test $DEVICETYPE = PCI -o $DEVICETYPE = USB; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+const struct dev_entry devs_${PROGRAMMERNAME}[] = {
+ {0xdead, 0xbeef, NT, "Vendor name", "Device name"},
+
+ {0},
+};
+
+EOF
+fi
+
+if test $NEED_PARLPCFWH = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+static void ${PROGRAMMERNAME}_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
+{
+ /* Write a byte to the flash chip. */
+}
+
+static uint8_t ${PROGRAMMERNAME}_chip_readb(const struct flashctx *flash, const chipaddr addr)
+{
+ /* Read a byte from the flash chip and return it. */
+ /* Set it to 0xff to get the template to compile. */
+ uint8_t val = 0xff;
+
+ return val;
+}
+
+static const struct par_programmer par_programmer_${PROGRAMMERNAME} = {
+ .chip_readb = ${PROGRAMMERNAME}_chip_readb,
+ /* If your programmer supports word/long accesses, change the lines below. */
+ .chip_readw = fallback_chip_readw,
+ .chip_readl = fallback_chip_readl,
+ .chip_readn = fallback_chip_readn,
+ .chip_writeb = ${PROGRAMMERNAME}_chip_writeb,
+ .chip_writew = fallback_chip_writew,
+ .chip_writel = fallback_chip_writel,
+ .chip_writen = fallback_chip_writen,
+};
+
+EOF
+fi
+
+if test $NEED_SPI_BITBANG = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+static void ${PROGRAMMERNAME}_bitbang_set_cs(int val)
+{
+ /* Set/clear the CS# line. */
+}
+
+static void ${PROGRAMMERNAME}_bitbang_set_sck(int val)
+{
+ /* Set/clear the SCLK line. */
+}
+
+static void ${PROGRAMMERNAME}_bitbang_set_mosi(int val)
+{
+ /* Set/clear the MOSI line. */
+}
+
+static int ${PROGRAMMERNAME}_bitbang_get_miso(void)
+{
+ /* Get the state of the MISO line and return it. */
+ /* Set it to 1 to get the template to compile. */
+ int misoval = 1;
+
+ return misoval;
+}
+
+/* If this programmer does not support requesting/releasing the SPI bus, remove
+ * the functions ${PROGRAMMERNAME}_request_spibus and ${PROGRAMMERNAME}_release_spibus
+ * and set bitbang_spi_master_${PROGRAMMERNAME} members .request_bus and .release_bus
+ * to NULL.
+ */
+static void ${PROGRAMMERNAME}_request_spibus(void)
+{
+}
+
+static void ${PROGRAMMERNAME}_release_spibus(void)
+{
+}
+
+static const struct bitbang_spi_master bitbang_spi_master_${PROGRAMMERNAME} = {
+ .set_cs = ${PROGRAMMERNAME}_bitbang_set_cs,
+ .set_sck = ${PROGRAMMERNAME}_bitbang_set_sck,
+ .set_mosi = ${PROGRAMMERNAME}_bitbang_set_mosi,
+ .get_miso = ${PROGRAMMERNAME}_bitbang_get_miso,
+ .request_bus = ${PROGRAMMERNAME}_request_spibus,
+ .release_bus = ${PROGRAMMERNAME}_release_spibus,
+ .half_period = 1, /* Delay in microseconds before each SCLK level change. */
+};
+
+EOF
+fi
+
+if test $NEED_SPI = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+/* Include string.h for memset to get the template to compile. Remove this. */
+#include <string.h>
+static int ${PROGRAMMERNAME}_spi_send_command(struct flashctx *flash,
+ unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr,
+ unsigned char *readarr)
+{
+ /* Send a SPI command to the flash chip. */
+ /* Set readarr to 0xff to get the template to compile and run without segfaults. */
+ memset(readarr, 0xff, readcnt);
+
+ return 0;
+}
+
+static const struct spi_master spi_master_${PROGRAMMERNAME} = {
+ .max_data_read = 64 * 1024, /* Maximum data read size in one go (excluding opcode+address). */
+ .max_data_write = 256, /* Maximum data write size in one go (excluding opcode+address). */
+ .command = ${PROGRAMMERNAME}_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+};
+
+EOF
+fi
+
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+static int ${PROGRAMMERNAME}_shutdown(void *data)
+{
+ /* Shutdown stuff. */
+ return 0;
+}
+
+int ${PROGRAMMERNAME}_init(void)
+{
+ /* Init stuff (i.e. parameter parsing) here which does not need to be
+ * undone.
+ */
+
+ /* If your shutdown function takes a parameter, replace NULL with it. */
+ register_shutdown(${PROGRAMMERNAME}_shutdown, NULL);
+
+ /* Init stuff which needs to be undone on shutdown. */
+
+EOF
+
+if test $NEED_SPI_BITBANG = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+ /* 1 usec halfperiod delay, change as needed. */
+ if (bitbang_spi_init(&bitbang_spi_master_${PROGRAMMERNAME}))
+ return 1;
+
+EOF
+fi
+
+if test $NEED_SPI = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+ register_spi_master(&spi_master_${PROGRAMMERNAME});
+
+EOF
+fi
+
+if test $NEED_PARLPCFWH = yes; then
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+ register_par_programmer(&par_programmer_${PROGRAMMERNAME}, BUS_${BUS_PARLPCFWH});
+
+EOF
+fi
+
+cat >>$PROGRAMMERNAME.c.mine <<EOF
+ return 0;
+}
+EOF
+
+csplit -f .newmeson_options meson_options.txt "/#PLACEHOLDER_NEWPROG_MESON_OPTION_START/+1" "/#PLACEHOLDER_NEWPROG_MESON_OPTION_END/"
+echo "option('config_${PROGRAMMERNAME}', type : 'boolean', value : true, description : '${PROGRAMMERDESCR}')" >>.newmeson_options01
+sort .newmeson_options01 >.newmeson_options03
+cat .newmeson_options00 .newmeson_options03 .newmeson_options02 >meson_options.txt.mine
+rm .newmeson_options00 .newmeson_options01 .newmeson_options02 .newmeson_options03
+
+csplit -f .newmeson meson.build "/#PLACEHOLDER_NEWPROG_MESON_CONFIGFETCH_START/+1" "/#PLACEHOLDER_NEWPROG_MESON_CONFIGFETCH_END/"
+echo "config_${PROGRAMMERNAME} = get_option('config_${PROGRAMMERNAME}')" >>.newmeson01
+sort .newmeson01 >.newmeson03
+cat .newmeson00 .newmeson03 .newmeson02 >.newmeson.build.mine
+rm .newmeson00 .newmeson01 .newmeson02 .newmeson03
+
+if test $DEVICETYPE = PCI ; then
+ csplit -f .newmeson .newmeson.build.mine "/#PLACEHOLDER_NEWPROG_MESON_PCI_REQUIREMENT_MISSING_START/+1" "/#PLACEHOLDER_NEWPROG_MESON_PCI_REQUIREMENT_MISSING_END/"
+ echo " config_${PROGRAMMERNAME} = false" >>.newmeson01
+ sort .newmeson01 >.newmeson03
+ cat .newmeson00 .newmeson03 .newmeson02 >.newmeson.build.mine
+ rm .newmeson00 .newmeson01 .newmeson02 .newmeson03
+fi
+
+if test $DEVICETYPE = USB ; then
+ csplit -f .newmeson .newmeson.build.mine "/#PLACEHOLDER_NEWPROG_MESON_USB_REQUIREMENT_MISSING_START/+1" "/#PLACEHOLDER_NEWPROG_MESON_USB_REQUIREMENT_MISSING_END/"
+ echo " config_${PROGRAMMERNAME} = false" >>.newmeson01
+ sort .newmeson01 >.newmeson03
+ cat .newmeson00 .newmeson03 .newmeson02 >.newmeson.build.mine
+ rm .newmeson00 .newmeson01 .newmeson02 .newmeson03
+fi
+
+csplit -f .newmeson .newmeson.build.mine "/#PLACEHOLDER_NEWPROG_MESON_FILES_DEFINES_NEEDS_START/+1" "/#PLACEHOLDER_NEWPROG_MESON_FILES_DEFINES_NEEDS_END/"
+# FIXME: The current meson.build always builds the PCI intrastructure unless explicitly disabled.
+cat >>.newmeson01 <<EOF
+if config_${PROGRAMMERNAME}
+ srcs += '${PROGRAMMERNAME}.c'
+ cargs += '-D${CONFIGNAME}=1'
+EOF
+if $NEED_SERIAL = yes; then
+ cat >>.newmeson01 <<EOF
+ need_serial = true
+EOF
+cat >>.newmeson01 <<EOF
+endif
+EOF
+# FIXME: Sorting is a bit more complicated here. Skip it for now.
+cat .newmeson00 .newmeson01 .newmeson02 >.newmeson.build.mine
+rm .newmeson00 .newmeson01 .newmeson02
+
+mv .newmeson.build.mine meson.build.mine
+
+echo "The driver skeleton has been created in $PROGRAMMERNAME.c.mine"
+echo "Modified versions of existing files have been created with extension .mine"
+echo "You can replace the original files with the modified versions by running"
+echo "for a in *; do test -f \$a.mine && mv \$a.mine \$a; done"
+echo "If you want to use the newly generated skeleton $PROGRAMMERNAME.c.mine , run"
+echo "mv $PROGRAMMERNAME.c.mine $PROGRAMMERNAME.c"
+echo
+echo "WARNING: Please note that rerunning build_new_driver.sh will overwrite"
+echo "all *.mine files, but it won't touch $PROGRAMMERNAME.c ."
+echo "If something goes wrong, you can revert all files which look odd and"
+echo "run this script again."
@@ -602,7 +602,7 @@
#define PMC_PM49FL004 0x6E
/*
- * The Sanyo chip found so far uses SPI, first byte is manufacture code,
+ * The Sanyo chip found so far uses SPI, first byte is manufacturer code,
* second byte is the device code,
* third byte is a dummy byte.
*/
@@ -345,6 +345,9 @@
.sp
.BR "* stlinkv3_spi" " (for SPI flash ROMs attached to STMicroelectronics STLINK V3 devices)"
.sp
+.BR "* vl805" " (VIA VL805 programmer)"
+.sp
+.\"PLACEHOLDER_NEWPROG_MAN_SHORTDESCRIPTION
Some programmers have optional or mandatory parameters which are described
in detail in the
.B PROGRAMMER-SPECIFIC INFORMATION
@@ -1287,7 +1290,10 @@
If the passed frequency is not supported by the adapter the nearest lower
supported frequency will be used.
.SS
-
+.BR "vl805 " programmer
+Please describe the programmer parameters here.
+.SS
+.\"PLACEHOLDER_NEWPROG_MAN_LONGDESCRIPTION
.SH EXAMPLES
To back up and update your BIOS, run
.sp
@@ -1365,6 +1371,10 @@
.B ogp
needs PCI configuration space read access and raw memory access.
.sp
+.B vl805
+Please describe the programmer requirements here.
+.sp
+.\"PLACEHOLDER_NEWPROG_MAN_REQUIREMENTS
On OpenBSD, you can obtain raw access permission by setting
.B "securelevel=-1"
in
@@ -473,6 +473,19 @@
},
#endif
+#if CONFIG_VL805 == 1
+ {
+ .name = "vl805",
+ .type = PCI,
+ .devs.dev = devs_vl805,
+ .init = vl805_init,
+ .map_flash_region = fallback_map,
+ .unmap_flash_region = fallback_unmap,
+ .delay = internal_delay,
+ },
+#endif
+
+//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY
{0}, /* This entry corresponds to PROGRAMMER_INVALID. */
};
@@ -30,6 +30,7 @@
add_project_arguments('-DFLASHROM_VERSION="' + meson.project_version() + '"', language : 'c')
# get defaults from configure
+# PLACEHOLDER_NEWPROG_MESON_CONFIGFETCH_START
config_atahpt = get_option('config_atahpt')
config_atapromise = get_option('config_atapromise')
config_atavia = get_option('config_atavia')
@@ -62,6 +63,7 @@
config_serprog = get_option('config_serprog')
config_usbblaster_spi = get_option('config_usbblaster_spi')
config_stlinkv3_spi = get_option('config_stlinkv3_spi')
+# PLACEHOLDER_NEWPROG_MESON_CONFIGFETCH_END
cargs = []
deps = []
@@ -86,11 +88,13 @@
srcs += 'usbdev.c'
deps += dependency('libusb-1.0')
else
+# PLACEHOLDER_NEWPROG_MESON_USB_REQUIREMENT_MISSING_START
config_ch341a_spi = false
config_dediprog = false
config_digilent_spi = false
config_developerbox_spi = false
config_pickit2_spi = false
+# PLACEHOLDER_NEWPROG_MESON_USB_REQUIREMENT_MISSING_END
endif
# some programmers require libpci
@@ -99,6 +103,7 @@
deps += dependency('libpci')
cargs += '-DNEED_PCI=1'
else
+# PLACEHOLDER_NEWPROG_MESON_PCI_REQUIREMENT_MISSING_START
config_atahpt = false
config_atapromise = false
config_atavia = false
@@ -116,9 +121,11 @@
config_rayer_spi = false
config_satamv = false
config_satasii = false
+# PLACEHOLDER_NEWPROG_MESON_PCI_REQUIREMENT_MISSING_END
endif
# set defines for configured programmers
+# PLACEHOLDER_NEWPROG_MESON_FILES_DEFINES_NEEDS_START
if config_atahpt
srcs += 'atahpt.c'
cargs += '-DCONFIG_ATAHPT=1'
@@ -276,6 +283,7 @@
srcs += 'stlinkv3_spi.c'
cargs += '-DCONFIG_STLINKV3_SPI=1'
endif
+# PLACEHOLDER_NEWPROG_MESON_FILES_DEFINES_NEEDS_END
# bitbanging SPI infrastructure
if config_bitbang_spi
@@ -1,6 +1,7 @@
option('pciutils', type : 'boolean', value : true, description : 'use pciutils')
option('usb', type : 'boolean', value : true, description : 'use libusb1')
+#PLACEHOLDER_NEWPROG_MESON_OPTION_START
option('config_atahpt', type : 'boolean', value : false, description : 'Highpoint (HPT) ATA/RAID controllers')
option('config_atapromise', type : 'boolean', value : false, description : 'Promise ATA controller')
option('config_atavia', type : 'boolean', value : true, description : 'VIA VT6421A LPC memory')
@@ -33,3 +34,4 @@
option('config_satasii', type : 'boolean', value : true, description : 'SiI SATA controllers')
option('config_serprog', type : 'boolean', value : true, description : 'serprog')
option('config_usbblaster_spi', type : 'boolean', value : true, description : 'Altera USB-Blaster dongles')
+#PLACEHOLDER_NEWPROG_MESON_OPTION_END
@@ -148,33 +148,6 @@
return (uintptr_t)addr;
}
-static uintptr_t pcidev_validate(struct pci_dev *dev, int bar, const struct dev_entry *devs)
-{
- unsigned i;
-
- /* Check against list of supported devices. */
- for (i = 0; devs[i].device_name != NULL; i++) {
- if (dev->device_id != devs[i].device_id)
- continue;
-
- msg_pinfo("Found \"%s %s\" (%04x:%04x, BDF %02x:%02x.%x).\n",
- devs[i].vendor_name, devs[i].device_name,
- dev->vendor_id, dev->device_id, dev->bus, dev->dev,
- dev->func);
-
- if (devs[i].status == NT)
- msg_pinfo("===\nThis PCI device is UNTESTED. Please report the 'flashrom -p "
- "xxxx' output\n"
- "to flashrom@flashrom.org if it works for you. Please add the name "
- "of your\n"
- "PCI device to the subject. Thank you for your help!\n===\n");
-
-
- return pcidev_readbar(dev, bar);
- }
- return 0;
-}
-
static int pcidev_shutdown(void *data)
{
if (pacc == NULL) {
@@ -210,10 +183,12 @@
struct pci_dev *pcidev_init(const struct dev_entry *devs, int bar)
{
struct pci_dev *dev;
+ struct pci_dev *found_dev = NULL;
struct pci_filter filter;
char *pcidev_bdf;
char *msg = NULL;
int found = 0;
+ int i;
uintptr_t addr = 0;
if (pci_init_common() != 0)
@@ -232,10 +207,30 @@
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
+ /* Check against list of supported devices. */
+ for (i = 0; devs[i].device_name != NULL; i++)
+ if ((dev->vendor_id == devs[i].vendor_id) &&
+ (dev->device_id == devs[i].device_id))
+ break;
+ /* Not supported, try the next one. */
+ if (devs[i].device_name == NULL)
+ continue;
+
+ msg_pdbg("Found \"%s %s\" (%04x:%04x, BDF %02x:%02x.%x).\n", devs[i].vendor_name,
+ devs[i].device_name, dev->vendor_id, dev->device_id, dev->bus, dev->dev,
+ dev->func);
+ if (devs[i].status == NT)
+ msg_pinfo("===\nThis PCI device is UNTESTED. Please report the 'flashrom -p "
+ "xxxx' output\n"
+ "to flashrom@flashrom.org if it works for you. Please add the name "
+ "of your\n"
+ "PCI device to the subject. Thank you for your help!\n===\n");
+
/* FIXME: We should count all matching devices, not
* just those with a valid BAR.
*/
- if ((addr = pcidev_validate(dev, bar, devs)) != 0) {
+ if ((addr = pcidev_readbar(dev, bar)) != 0) {
+ found_dev = dev;
found++;
}
}
@@ -251,7 +246,7 @@
return NULL;
}
- return dev;
+ return found_dev;
}
enum pci_write_type {
@@ -127,6 +127,10 @@
#if CONFIG_STLINKV3_SPI == 1
PROGRAMMER_STLINKV3_SPI,
#endif
+#if CONFIG_VL805 == 1
+ PROGRAMMER_VL805,
+#endif
+//PLACEHOLDER_NEWPROG_PROGRAMMER_ENUM
PROGRAMMER_INVALID /* This must always be the last entry. */
};
@@ -573,6 +577,15 @@
int ni845x_spi_init(void);
#endif
+/* vl805.c */
+#if CONFIG_VL805 == 1
+int vl805_init(void);
+extern const struct dev_entry devs_vl805[];
+
+#endif
+
+//PLACEHOLDER_NEWPROG_PUBLICFUNCTIONS
+
/* flashrom.c */
struct decode_sizes {
uint32_t parallel;
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2019, 2020 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
+ */
+
+/* Driver for the VIA VL805 programmer hardware by VIA.
+ * See http://www.via.com/ for more info.
+ */
+
+#include "flash.h"
+#include "programmer.h"
+#include "hwaccess.h"
+#include "spi.h"
+
+const struct dev_entry devs_vl805[] = {
+ {0x1106, 0x3483, NT, "VIA", "VL805"},
+
+ {0},
+};
+
+static struct pci_dev *dev = NULL;
+
+static void vl805_setregval(int reg, uint32_t val)
+{
+ pci_write_long(dev, 0x78, reg);
+ pci_write_long(dev, 0x7c, val);
+}
+
+static uint32_t vl805_getregval(int reg)
+{
+ pci_write_long(dev, 0x78, reg);
+ return pci_read_long(dev, 0x7c);
+}
+
+/* Some of the registers have unknown purpose and are just used inside the init sequence replay. */
+#define VL805_REG_0x30004 0x00030004
+#define VL805_REG_STOP_POLLING 0x0004000c
+#define VL805_REG_WB_EN 0x00040020
+#define VL805_REG_SPI_OUTDATA 0x000400d0
+#define VL805_REG_SPI_INDATA 0x000400e0
+#define VL805_REG_SPI_TRANSACTION 0x000400f0
+#define VL805_REG_CLK_DIV 0x000400f8
+#define VL805_REG_SPI_CHIP_ENABLE_LEVEL 0x000400fc
+
+/* Send a SPI command to the flash chip. */
+static int vl805_spi_send_command(struct flashctx *flash,
+ unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr,
+ unsigned char *readarr)
+{
+ unsigned int i, j;
+ uint32_t outdata;
+ uint32_t indata = 0;
+ unsigned int curwritecnt = 0;
+ unsigned int curreadcnt = 0;
+
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000000);
+
+ for (j = 0; j < writecnt; j += 4) {
+ curwritecnt = min(4, writecnt - j);
+ outdata = 0;
+ for (i = 0; i < curwritecnt; i++) {
+ outdata <<= 8;
+ outdata |= writearr[j + i];
+ }
+ vl805_setregval(VL805_REG_SPI_OUTDATA, outdata);
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000580 | (curwritecnt << 3));
+ }
+
+ /* Superfluous, the original driver doesn't do that, but we want to have a quiet bus during read. */
+ vl805_setregval(VL805_REG_SPI_OUTDATA, 0);
+
+ for (j = 0; j < readcnt; j += 4) {
+ curreadcnt = min(4, readcnt - j);
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000580 | (curreadcnt << 3));
+ indata = vl805_getregval(VL805_REG_SPI_INDATA);
+ for (i = 0; i < curreadcnt; i++) {
+ readarr[j + i] = indata & 0xff;
+ indata >>= 8;
+ }
+ }
+
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000001);
+ return 0;
+}
+
+static const struct spi_master spi_master_vl805 = {
+ .max_data_read = 64 * 1024, /* Maximum data read size in one go (excluding opcode+address). */
+ .max_data_write = 256, /* Maximum data write size in one go (excluding opcode+address). */
+ .command = vl805_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+};
+
+static void vl805_programmer_active(uint8_t val)
+{
+ pci_write_byte(dev, 0x43, val);
+}
+
+static int vl805_shutdown(void *data)
+{
+ /* Shutdown stuff. */
+ vl805_programmer_active(0x0);
+ return 0;
+}
+
+int vl805_init(void)
+{
+ if (rget_io_perms())
+ return 1;
+
+ dev = pcidev_init(devs_vl805, PCI_BASE_ADDRESS_0); /* Actually no BAR setup needed at all. */
+ if (!dev)
+ return 1;
+
+ vl805_programmer_active(0x1);
+ uint32_t val = pci_read_long(dev, 0x50);
+ msg_pdbg("VL805 firmware version 0x%08x\n", val);
+ vl805_programmer_active(0x0);
+
+ /* Some sort of init sequence, just copied from the logs. */
+ vl805_programmer_active(0x1);
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000001);
+ val = vl805_getregval(VL805_REG_0x30004);
+ if (val != 0x00000200) {
+ msg_perr("VL805_REG_0x30004 returned unexpected value 0x%08x\n", val);
+ return 1;
+ }
+ vl805_setregval(VL805_REG_0x30004, 0x00000200);
+ val = vl805_getregval(VL805_REG_WB_EN);
+ if (val != 0xffffffff) {
+ msg_perr("VL805_REG_WB_EN returned unexpected value 0x%08x\n", val);
+ return 1;
+ }
+ vl805_setregval(VL805_REG_WB_EN, 0xffffff01);
+ val = vl805_getregval(VL805_REG_STOP_POLLING);
+ if (val != 0x00000001) {
+ msg_perr("VL805_REG_STOP_POLLING returned unexpected value 0x%08x\n", val);
+ return 1;
+ }
+ vl805_setregval(VL805_REG_STOP_POLLING, 0x00000001);
+ /* We send 4 uninitialized(?) bytes to the flash chip here. */
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x000005a0);
+ vl805_setregval(VL805_REG_CLK_DIV, 0x0000000a);
+
+ /* Some sort of cleanup sequence, just copied from the logs. */
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000000);
+ vl805_programmer_active(0x0);
+
+ register_shutdown(vl805_shutdown, NULL);
+ vl805_programmer_active(0x1);
+
+ register_spi_master(&spi_master_vl805);
+
+ return 0;
+}
VIA VL805 support, first draft. No idea if it actually works. It is highly likely that SPI accesses with a readcnt not being a multiple of 4 will return incorrect data due to the unknown encoding of the register containing SPI responses of the chip. That will be obvious from any verbose log, though, and once I have such data, adjusting the code is trivial. Reverse engineered based on PCI traces created by cleverca22 on a Raspberry Pi 4 Model B. RFC, with some unrelated (automatic programmer driver writer) and some related changes (buggy PCI patch reverted). In case someone is feeling less brave, I also have a version which aborts early after the init sequence. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>