Hi all

I tried with IMC activated on coreboot (Hudson chipset) and it works as expected. Attached patch only tweaks messages and removes now redundant check from sb600 SPI. If IMC is active and firmware handoff fails, then it exits with fatal error.

Signed-off-by: Rudolf Marek <[email protected]>

It would be nice if someone else could test this (and dont forget to be able to recover from bad flash)

Thanks
Rudolf
Index: Makefile
===================================================================
--- Makefile	(revision 1657)
+++ Makefile	(working copy)
@@ -417,7 +417,7 @@
 FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
 PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o dmi.o internal.o
 ifeq ($(ARCH), x86)
-PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o wbsio_spi.o mcp6x_spi.o
+PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o imc.o wbsio_spi.o mcp6x_spi.o
 PROGRAMMER_OBJS += ichspi.o ich_descriptors.o
 else
 endif
Index: imc.c
===================================================================
--- imc.c	(revision 0)
+++ imc.c	(revision 0)
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2013 Rudolf Marek <[email protected]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "flash.h"
+#include "programmer.h"
+#include "hwaccess.h"
+#include "spi.h"
+
+/* same as serverengines */
+static void enter_conf_mode_ec(uint16_t port)
+{
+	outb(0x5a, port);
+}
+
+static void exit_conf_mode_ec(uint16_t port)
+{
+	outb(0xa5, port);
+}
+
+static uint16_t get_sio_port(struct pci_dev *dev)
+{
+	uint16_t ec_port;
+
+	if (!dev) {
+		return 0;
+	}
+
+	if (!(pci_read_byte(dev, 0x40) & (1 << 7)))
+		return 0;
+
+	ec_port = pci_read_word(dev, 0xa4);
+
+	if (!(ec_port & 0x1))
+		return 0;
+
+	ec_port &= ~0x1;
+
+	return ec_port;
+}
+
+
+static void write_data(uint16_t port, uint8_t off, uint8_t data)
+{
+	outb(off, port);
+	outb(data, port + 1);
+}
+
+static uint8_t read_data(uint16_t port, uint8_t off)
+{
+	outb(off, port);
+	return inb(port + 1);
+}
+
+
+static uint16_t get_mbox_port(uint16_t sio_port)
+{
+	uint16_t mbox_port;
+
+	enter_conf_mode_ec(sio_port);
+
+	/* go to LDN 9, mailbox */
+	write_data(sio_port, 7, 9);
+
+	/* MBOX not active ? */
+	if (!(read_data(sio_port, 0x30) & 1)) {
+		exit_conf_mode_ec(sio_port);
+		return 0;
+	}
+
+	mbox_port = read_data(sio_port, 0x60) << 8;
+	mbox_port |= read_data(sio_port, 0x61);
+
+	exit_conf_mode_ec(sio_port);
+	return mbox_port;
+}
+
+static int mbox_wait_ack(uint16_t mbox_port)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		/* sleep 1ms */
+		programmer_delay(1000);
+		if (read_data(mbox_port, 0x82) == 0xfa) {
+			return 0;
+		}
+	}
+	msg_pwarn("IMC MBOX: Timeout!\n");
+	return 1;
+
+}
+
+static int send_cmd(uint16_t mbox_port, uint8_t cmd)
+{
+	write_data(mbox_port, 0x82, 0x0);
+	write_data(mbox_port, 0x83, cmd);
+	/* trigger transfer 0x96 with subcommand cmd */
+	write_data(mbox_port, 0x80, 0x96);
+
+	return mbox_wait_ack(mbox_port);
+}
+
+static int imc_cmd(struct pci_dev *dev, uint8_t cmd)
+{
+	uint16_t sio_port;
+	uint16_t mbox_port;
+	sio_port = get_sio_port(dev);
+
+	if (!sio_port)
+		return -1;
+
+	msg_pdbg("\nEC SIO is at 0x%x\n", sio_port);
+
+	mbox_port = get_mbox_port(sio_port);
+
+	if (!mbox_port)
+		return -1;
+
+	msg_pdbg("EC MBOX is at 0x%x\n", mbox_port);
+
+	/* put IMC to sleep */
+	return send_cmd(mbox_port, cmd);
+}
+
+static int imc_try_resume(void *data)
+{
+	struct pci_dev *dev = data;
+	int ret = imc_cmd(dev, 0xb5);
+
+	msg_pinfo("(IMC resume%s)\n", ret ? " failed!" : "d");
+	return ret;
+}
+
+int imc_try_shutdown(struct pci_dev *dev)
+{
+	int ret = imc_cmd(dev, 0xb4);
+
+	/* No IMC active, fake OK */
+	if (ret < 0)
+		return 0;
+
+	msg_pinfo("(Shutting down IMC%s)\n", ret ? " failed!" : "");
+
+	/* restore IMC on exit */
+	if ((!ret) && (register_shutdown(imc_try_resume, dev)))
+		return 1;
+
+	return ret;
+}
+
+#endif
\ No newline at end of file
Index: chipset_enable.c
===================================================================
--- chipset_enable.c	(revision 1657)
+++ chipset_enable.c	(working copy)
@@ -922,6 +922,10 @@
 	uint8_t reg;
 	int ret;
 
+	if (imc_try_shutdown(dev)) {
+		return ERROR_FATAL;
+	}
+
 	/* Clear ROM protect 0-3. */
 	for (reg = 0x50; reg < 0x60; reg += 4) {
 		prot = pci_read_long(dev, reg);
Index: sb600spi.c
===================================================================
--- sb600spi.c	(revision 1657)
+++ sb600spi.c	(working copy)
@@ -301,21 +301,6 @@
 
 	reg = pci_read_byte(dev, 0x40);
 	msg_pdbg("SB700 IMC is %sactive.\n", (reg & (1 << 7)) ? "" : "not ");
-	if (reg & (1 << 7)) {
-		/* If we touch any region used by the IMC, the IMC and the SPI
-		 * interface will lock up, and the only way to recover is a
-		 * hard reset, but that is a bad choice for a half-erased or
-		 * half-written flash chip.
-		 * There appears to be an undocumented register which can freeze
-		 * or disable the IMC, but for now we want to play it safe.
-		 */
-		msg_perr("The SB700 IMC is active and may interfere with SPI "
-			 "commands. Disabling write.\n");
-		/* FIXME: Should we only disable SPI writes, or will the lockup
-		 * affect LPC/FWH chips as well?
-		 */
-		programmer_may_write = 0;
-	}
 
 	/* Bring the FIFO to a clean state. */
 	reset_internal_fifo_pointer();
Index: programmer.h
===================================================================
--- programmer.h	(revision 1657)
+++ programmer.h	(working copy)
@@ -559,6 +559,9 @@
 		 enum ich_chipset ich_generation);
 int via_init_spi(struct pci_dev *dev, uint32_t mmio_base);
 
+/* imc.c */
+int imc_try_shutdown(struct pci_dev *dev);
+
 /* it85spi.c */
 int it85xx_spi_init(struct superio s);
 
_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to