From patchwork Wed Jan 15 12:29:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carl-Daniel Hailfinger X-Patchwork-Id: 1223423 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.helo=coreboot.org (client-ip=78.46.105.101; helo=coreboot.org; envelope-from=flashrom-bounces@flashrom.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gmx.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.a=rsa-sha256 header.s=badeba3b8450 header.b=DwaBQkG7; dkim-atps=neutral Received: from coreboot.org (coreboot.org [78.46.105.101]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47yRX070z2z9sSd for ; Wed, 15 Jan 2020 23:31:27 +1100 (AEDT) Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) by coreboot.org (Postfix) with ESMTPA id 2D178208F2; Wed, 15 Jan 2020 12:31:19 +0000 (UTC) Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) by coreboot.org (Postfix) with ESMTP id 2399E20949 for ; Wed, 15 Jan 2020 12:31:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1579091461; bh=x+j4284iC9rfw4noACqWDJdYaO2ntNaesYk7Mh61wwA=; h=X-UI-Sender-Class:To:From:Subject:Date; b=DwaBQkG7WlTQkt7HEQ1teEws/JPU7xv7ElJ+vrqwWECll+bqxAOm9Huylamzt7ba6 cw/tYTxIuS1u/LawFGIC5g7eBUpxVQmtUhzy22gMyW2pdAkR3nYi29zxLaYP0uR/hU m1tUVw6cIydQe5/HDmf+C8FXjVP45i+5R8D7p4eo= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) [212.227.17.168]) with ESMTPSA (Nemesis) id 1MY68T-1jAFvE2K0z-00YPO6 for ; Wed, 15 Jan 2020 13:31:01 +0100 To: flashrom From: Carl-Daniel Hailfinger Message-ID: <5ddf65c1-2361-98cd-37ce-abb373d85ab7@gmx.net> Date: Wed, 15 Jan 2020 13:29:44 +0100 MIME-Version: 1.0 Content-Language: en-US X-Provags-ID: V03:K1:Z+lUVyy9zGrqs+hNwPDVAH9ERNWfqF2ipBeXhQ/yidCZmLjMixU Vvb+aw5AQOwcteLLeJgJgcUSEsRdYES266uIinaifGhQpWnPUkZrJmqshODohF9M1EuQxjo pv9qW49hHHWrDSNRPAM1XeJr6N8X3Mwjm3FlO5MIUApoSIvLk9znigTNeKrucSuUAEtDDuZ HhrLLo+qcGjfB/gg7E2ZQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:Y+ggaN35lEc=:QkY39BDCx8vVAnUfX/xTeV uUp5FMpJfK3MbMS4OMd6gqkoByA490DS4DK0kn6yVRbRBCAaCoFDluuJZ/cL+SVazxX1kCx21 UUY4NB1nu6sf4QVqh5uM3TLjxT3owIpYVg+Fc7TgMLrxXNtCUL5pOjfI5TByehEMsdmJj66cM MoXCt+v3DLD8682cPN1guBU1m8p9OqDFK+Pm6G+OZAXuvKCxVyahwl1tdEP72GOW2qz92WQEt wnKxQZfxKw1BMYLAIyg7OaOLeS3mPXQMqaeCQJ+JK/XLSgvQkLmfp+NUs4GY/SUcDQ0Ld0F0n iuiv2Ci7KRvXTx12DZ69mHFUDe5pURu0j2HE5vX7CzgyHt30AQ9RvnCPituA2HvcPR+wut68r PCm3R8vhwCBB2DKzIpKIpltcTQIiBl2JY0Wx4zFkiZuIBTWuB1Bn+cRjNZnmoZVYCg/7d369j UmbV3hXVkMCWa1tozH/zwzUAm2ko99YSb3tebWMhIKLKYKCD28x8cbOe449RgqnCudp1ugF5t EplyBaqo3d5FYKHO1v/1qXZEfw72mOC0zCtDb+NRgmgwDefkKWMvR1aT93HwV+PcZUxxORoZo B+gCJJKuUHf1ZAznbRmvuVwZktIIWcws4NGge5mb5NQgIQpRQaz+2Ai//W7SREnoFEQ4m0oFy wvcAY1V0XtK7wsd2L/tkhagq+Gg1tFpxrUAefD333mcorFYZYFJ4g3Xg+SMJqD/7mQKSH34/+ Y4Butq6RVgMbCZucfal4Hj/UHGvFs44eup0xqvIK47HTTjbB2WoQit/gLColNgssvv8KR6ph7 0ij7QnNeu/YrRww3SFqTBf6knrEbTYmRHF8RK0jHzz2/Bi/K9KIOtjen+w5nEMiOlsPqkLO3D i7X2XEyT3gvMyWdlvccVvMKBiUk+NRWF+p4XtfSgi7bmluiNpORhRpzf4758wObboOmHBxAkc 1oYC20LYp1Y0odBWm6slw0hq6KZnk06Iv+3U/sy0MNyTmgexmvpE5hylqvFLBG3jNqROFgz0Q IXWqPhNkhiT8vMubmjGUw4kyPYTum67uB6hHv5xcwzXkH+TW7s9tKN7KHjsvdveYDdcsE/yZK MeDW/o/bIcHkiP61GwwgG1QZYWyW0fHkitTBGEgOseMd0teNRX6SBIkgAoK2+RYBLBQ2CNhtT jEHsOlgZi10PuBz9xj67Ay5FFNi3Ue1bhtzgSyL7I1YzkNfMFj9weNOkMaKQkbHenv/OxdlVl LhnrbW/uZVpUQN6s4lK+vpKpqyp089TrYZkLhIWudYO9qog3NSC4j6fkp3fb+aFdk9TE0WId9 BztLRyfK Message-ID-Hash: 5KREITYJIYAMPGJUMUA6ECHQRMBILL6J X-Message-ID-Hash: 5KREITYJIYAMPGJUMUA6ECHQRMBILL6J X-MailFrom: c-d.hailfinger.devel.2006@gmx.net X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-flashrom.flashrom.org-0; header-match-flashrom.flashrom.org-1; header-match-flashrom.flashrom.org-2; header-match-flashrom.flashrom.org-3; header-match-flashrom.flashrom.org-4; header-match-flashrom.flashrom.org-5; header-match-flashrom.flashrom.org-6; header-match-flashrom.flashrom.org-7; header-match-flashrom.flashrom.org-8; header-match-flashrom.flashrom.org-9; header-match-flashrom.flashrom.org-10; header-match-flashrom.flashrom.org-11; header-match-flashrom.flashrom.org-12; header-match-flashrom.flashrom.org-13; header-match-flashrom.flashrom.org-14; header-match-flashrom.flashrom.org-15; header-match-flashrom.flashrom.org-16; header-match-flashrom.flashrom.org-17; header-match-flashrom.flashrom.org-18; header-match-flashrom.flashrom.org-19; header-match-flashrom.flashrom.org-20; header-match-flashrom.flashrom.org-21; header-match-flashrom.flashrom.org- 22; header-match-flashrom.flashrom.org-23; header-match-flashrom.flashrom.org-24; header-match-flashrom.flashrom.org-25; header-match-flashrom.flashrom.org-26; header-match-flashrom.flashrom.org-27; header-match-flashrom.flashrom.org-28; header-match-flashrom.flashrom.org-29; header-match-flashrom.flashrom.org-30; header-match-flashrom.flashrom.org-31; header-match-flashrom.flashrom.org-32; header-match-flashrom.flashrom.org-33; header-match-flashrom.flashrom.org-34; header-match-flashrom.flashrom.org-35; header-match-flashrom.flashrom.org-36; header-match-flashrom.flashrom.org-37; header-match-flashrom.flashrom.org-38; header-match-flashrom.flashrom.org-39; header-match-flashrom.flashrom.org-40; header-match-flashrom.flashrom.org-41; header-match-flashrom.flashrom.org-42; header-match-flashrom.flashrom.org-43; header-match-flashrom.flashrom.org-44; header-match-flashrom.flashrom.org-45; header-match-flashrom.flashrom.org-46; header-match-flashrom.flashrom.org-47; header-match-flash rom.flashrom.org-48; header-match-flashrom.flashrom.org-49; header-match-flashrom.flashrom.org-50; header-match-flashrom.flashrom.org-51; header-match-flashrom.flashrom.org-52; header-match-flashrom.flashrom.org-53; header-match-flashrom.flashrom.org-54; header-match-flashrom.flashrom.org-55; header-match-flashrom.flashrom.org-56; header-match-flashrom.flashrom.org-57; header-match-flashrom.flashrom.org-58; header-match-flashrom.flashrom.org-59; header-match-flashrom.flashrom.org-60; header-match-flashrom.flashrom.org-61; header-match-flashrom.flashrom.org-62; header-match-flashrom.flashrom.org-63; header-match-flashrom.flashrom.org-64; header-match-flashrom.flashrom.org-65; header-match-flashrom.flashrom.org-66; header-match-flashrom.flashrom.org-67; header-match-flashrom.flashrom.org-68; header-match-flashrom.flashrom.org-69; header-match-flashrom.flashrom.org-70; header-match-flashrom.flashrom.org-71; header-match-flashrom.flashrom.org-72; header-match-flashrom.flashrom.org-73; n onmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.3.1 Precedence: list Subject: [flashrom] [PATCH] VIA VL805 support List-Id: flashrom discussion and development mailing list Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-Spamd-Bar: +++ X-Spam-Level: *** Authentication-Results: coreboot.org; auth=pass smtp.auth=mailman@coreboot.org smtp.mailfrom=flashrom-bounces@flashrom.org 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 diff -r 7bf17529e516 Makefile --- a/Makefile Tue Dec 31 18:22:02 2019 +0100 +++ b/Makefile Wed Jan 15 13:20:27 2020 +0100 @@ -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 diff -r 7bf17529e516 atavia.c --- a/atavia.c Tue Dec 31 18:22:02 2019 +0100 +++ b/atavia.c Wed Jan 15 13:20:27 2020 +0100 @@ -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; diff -r 7bf17529e516 build_new_driver.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_new_driver.sh Wed Jan 15 13:20:27 2020 +0100 @@ -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 <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine < +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 <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine <>$PROGRAMMERNAME.c.mine <>.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 <>.newmeson01 <>.newmeson01 <.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." diff -r 7bf17529e516 flashchips.h --- a/flashchips.h Tue Dec 31 18:22:02 2019 +0100 +++ b/flashchips.h Wed Jan 15 13:20:27 2020 +0100 @@ -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. */ diff -r 7bf17529e516 flashrom.8.tmpl --- a/flashrom.8.tmpl Tue Dec 31 18:22:02 2019 +0100 +++ b/flashrom.8.tmpl Wed Jan 15 13:20:27 2020 +0100 @@ -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 diff -r 7bf17529e516 flashrom.c --- a/flashrom.c Tue Dec 31 18:22:02 2019 +0100 +++ b/flashrom.c Wed Jan 15 13:20:27 2020 +0100 @@ -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. */ }; diff -r 7bf17529e516 meson.build --- a/meson.build Tue Dec 31 18:22:02 2019 +0100 +++ b/meson.build Wed Jan 15 13:20:27 2020 +0100 @@ -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 diff -r 7bf17529e516 meson_options.txt --- a/meson_options.txt Tue Dec 31 18:22:02 2019 +0100 +++ b/meson_options.txt Wed Jan 15 13:20:27 2020 +0100 @@ -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 diff -r 7bf17529e516 pcidev.c --- a/pcidev.c Tue Dec 31 18:22:02 2019 +0100 +++ b/pcidev.c Wed Jan 15 13:20:27 2020 +0100 @@ -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 { diff -r 7bf17529e516 programmer.h --- a/programmer.h Tue Dec 31 18:22:02 2019 +0100 +++ b/programmer.h Wed Jan 15 13:20:27 2020 +0100 @@ -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; diff -r 7bf17529e516 vl805.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vl805.c Wed Jan 15 13:20:27 2020 +0100 @@ -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; +}