Patchworkβ Board enable (EC sleep) for Acer Ferrari 3400

login
register
about
Submitter Michael Karcher
Date 2010-04-11 22:55:44
Message ID <1271026544-6788-1-git-send-email-flashrom@mkarcher.dialup.fu-berlin.de>
Download mbox | patch
Permalink /patch/1221/
State New
Headers show

Comments

Magnus Alm - 2010-04-11 22:50:37
HI!

"sudo flashrom" doesn't cause any problems now.

"sudo flashrom -r BACKUP.ROM" works also tho the created file is
smaller than the downloaded file.

-rw-r--r-- 1 root   root     524288 2010-04-12 00:36 BACKUP.ROM
-rw-r--r-- 1 magnus magnus   525894 2004-10-19 09:32 ZI5_3C23.WPH

That might not be so strange if the downloaded file also contains
information about "magic bits".

/Magnus


2010/4/12 Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>:
> BE WARNED: FLASHROM COMES WITH NO WARRANTY! THIS IS ESPECIALLY TRUE FOR
> LAPTOPS, AND ESPECIALLY ESPECIALLY TRUE FOR LAPTOPS WITH SHARED EC.
> Nevertheless, I think that trying to *read* flash contents with this patch
> is not more unsafe than reading without this patch. Be warned that a crashed
> EC might mean no fan control. Don't even *THINK* about erase/write until
> read works fine!
>
> This is the first system with EC sleep support in flashrom, and the first
> user of the register_shutdown infrastructure.
>
> PCI match uses one out of many chips with subsystem ID Acer:0x0057, and
> also the northbridge (with bogus subsystem ID). DMI match added just for
> safety, as fiddling with the KBC is dangerous.
>
> Signed-off-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
> ---
>  board_enable.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 100 insertions(+), 0 deletions(-)
>
> diff --git a/board_enable.c b/board_enable.c
> index f1f7953..ce82131 100644
> --- a/board_enable.c
> +++ b/board_enable.c
> @@ -29,6 +29,66 @@
>  #include "flash.h"
>
>  /*
> + * Functions for EC/KBC communication
> + *  port = 0x60 for KBC, port = 0x62 (typically) for EC
> + */
> +static int wait_uc_writebuf_empty(uint16_t port)
> +{
> +       int count;
> +       for (count = 0; count < 50; count++)
> +       {
> +               /* quit if OBF bit clear */
> +               if (!(INB(port + 4) & 2))
> +                       return 0;
> +               usleep(10000);
> +       }
> +       return -1;
> +}
> +
> +static int wait_uc_readbuf_full(uint16_t port)
> +{
> +       int count;
> +       for (count = 0; count < 50; count++)
> +       {
> +               /* quit if IBF bit set */
> +               if (INB(port + 4) & 1)
> +                       return 0;
> +               usleep(10000);
> +       }
> +       return -1;
> +}
> +
> +static int uc_send_command(uint16_t port, uint8_t command)
> +{
> +       if (wait_uc_writebuf_empty(port) != 0)
> +               return -1;
> +       OUTB(command, port + 4);
> +       return 0;
> +}
> +
> +#if 0
> +static int uc_send_data(uint16_t port, uint8_t command)
> +{
> +       if (wait_uc_writebuf_empty(port) != 0)
> +               return -1;
> +       OUTB(command, port);
> +       return 0;
> +}
> +#endif
> +
> +static int uc_read_data(uint16_t port)
> +{
> +       if (wait_uc_readbuf_full(port) != 0)
> +               return -1;
> +       return INB(port);
> +}
> +
> +static void uc_flush_data(uint16_t port)
> +{
> +       INB(port);
> +}
> +
> +/*
>  * Helper functions for many Winbond Super I/Os of the W836xx range.
>  */
>  /* Enter extended functions */
> @@ -1307,6 +1367,45 @@ static int it8712f_gpio3_1_raise(const char *name)
>        return it8712f_gpio_set(32, 1);
>  }
>
> +static void send_kbc_command(void * cmdptr)
> +{
> +       uc_send_command(0x60, *(uint8_t*)cmdptr);
> +}
> +
> +static int board_acer_ferrari3400(const char *name)
> +{
> +       static uint8_t enable_command = 0xAA;
> +       uint16_t pmio_base;
> +       struct pci_dev * dev;
> +
> +       dev = pci_dev_find(0x1106, 0x3177);
> +       if (!dev)
> +       {
> +               fprintf(stderr, "ERROR: %s - Can't find VT8235\n", name);
> +               return -1;
> +       }
> +       pmio_base = pci_read_word(dev, 0x88) & 0xFF80;
> +       if (pmio_base == 0 || pmio_base == 0xFF80)
> +       {
> +               fprintf(stderr, "ERROR: %s - invalid PMIO base %04x\n",
> +                               name, pmio_base);
> +               return -1;
> +       }
> +
> +       usleep(100000); /* Give the user a fair chance to release enter
> +                          before killing keyboard/mouse */
> +
> +        uc_flush_data(0x60);
> +       register_shutdown(send_kbc_command, &enable_command);
> +       if (INB(pmio_base + 4) & 1)
> +               uc_send_command(0x60, 0xE5);    /* ACPI mode */
> +       else
> +               uc_send_command(0x60, 0xD8);    /* APM/legacy mode */
> +
> +       uc_read_data(0x60);             /* wait for EC shutdown */
> +       return 0;
> +}
> +
>  /**
>  * Below is the list of boards which need a special "board enable" code in
>  * flashrom before their ROM chip can be accessed/written to.
> @@ -1356,6 +1455,7 @@ struct board_pciid_enable board_pciid_enables[] = {
>        {0x10de, 0x0050, 0x147b, 0x1c1a,       0,      0,      0,      0, NULL,          NULL,         NULL,          "Abit",        "KN8 Ultra",             0,   NT, nvidia_mcp_gpio2_lower},
>        {0x10de, 0x01e0, 0x147b, 0x1c00,  0x10de, 0x0060, 0x147B, 0x1c00, NULL,          NULL,         NULL,          "Abit",        "NF7-S",                 0,   OK, nvidia_mcp_gpio8_raise},
>        {0x1106, 0x0691,      0,      0,  0x1106, 0x3057,      0,      0, NULL,          "abit",       "vt6x4",       "Abit",        "VT6X4",                 0,   OK, via_apollo_gpo4_lower},
> +       {0x1106, 0x3177, 0x1025, 0x0057,  0x1106, 0x3188, 0x1106, 0x3188, "^Ferrari 3400", NULL,       NULL,          "Acer",        "Ferrari 3400",          0,   OK, board_acer_ferrari3400},
>        {0x105a, 0x0d30, 0x105a, 0x4d33,  0x8086, 0x1130, 0x8086,      0, NULL,          NULL,         NULL,          "Acorp",       "6A815EPD",              0,   OK, board_acorp_6a815epd},
>        {0x8086, 0x24D4, 0x1849, 0x24D0,  0x8086, 0x24D5, 0x1849, 0x9739, NULL,          NULL,         NULL,          "ASRock",      "P4i65GV",               0,   OK, intel_ich_gpio23_raise},
>        {0x1022, 0x746B,      0,      0,       0,      0,      0,      0, NULL,          "AGAMI",      "ARUMA",       "agami",       "Aruma",                 0,   OK, w83627hf_gpio24_raise_2e},
> --
> 1.7.0
>
>
Michael Karcher - 2010-04-11 22:55:44
BE WARNED: FLASHROM COMES WITH NO WARRANTY! THIS IS ESPECIALLY TRUE FOR
LAPTOPS, AND ESPECIALLY ESPECIALLY TRUE FOR LAPTOPS WITH SHARED EC.
Nevertheless, I think that trying to *read* flash contents with this patch
is not more unsafe than reading without this patch. Be warned that a crashed
EC might mean no fan control. Don't even *THINK* about erase/write until
read works fine!

This is the first system with EC sleep support in flashrom, and the first
user of the register_shutdown infrastructure.

PCI match uses one out of many chips with subsystem ID Acer:0x0057, and
also the northbridge (with bogus subsystem ID). DMI match added just for
safety, as fiddling with the KBC is dangerous.

Signed-off-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
---
 board_enable.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 100 insertions(+), 0 deletions(-)
Michael Karcher - 2010-04-12 00:00:48
Am Montag, den 12.04.2010, 00:50 +0200 schrieb Magnus Alm:
> "sudo flashrom" doesn't cause any problems now.
Cool, looks like I got it right.

> "sudo flashrom -r BACKUP.ROM" works also tho the created file is
> smaller than the downloaded file.
> 
> -rw-r--r-- 1 root   root     524288 2010-04-12 00:36 BACKUP.ROM
> -rw-r--r-- 1 magnus magnus   525894 2004-10-19 09:32 ZI5_3C23.WPH
> 
> That might not be so strange if the downloaded file also contains
> information about "magic bits".
The .WPH file format contains flashing instructions appended to the
image, while the BACKUP.ROM does not. Your backup is exactly 512*1024
bytes big. If you want to try flashing the new image (which will most
likely work), you should keep the data from the BACKUP.ROM at offsets
0x10000..0x11fff, as this 8KB area contains BIOS system information. (I
extracted this information from the appended stuff in the .WPH file)
The first 0xE000 bytes in your flash BIOS contain the code for the
embedded controller.

Regards,
  Michael Karcher
Magnus Alm - 2010-04-12 00:02:20
Tested flashing with the backup file:

sudo flashrom -w BACKUP.ROM
flashrom v0.9.1-r993 on Linux 2.6.32-19-generic (i686), built with
libpci 3.0.0, GCC 4.4.3
No coreboot table found.
========================================================================
WARNING! You seem to be running flashrom on a laptop.
Laptops, notebooks and netbooks are difficult to support and we recommend
to use the vendor flashing utility. The embedded controller (EC) in these
machines often interacts badly with flashing.
See http://www.flashrom.org/Laptops for details.
========================================================================
Found chipset "VIA VT8235", enabling flash write... OK.
This chipset supports the following protocols: Non-SPI.
Disabling flash write protection for board "Acer Ferrari 3400"... OK.
Calibrating delay loop... OK.
Found chip "SST SST39SF040" (512 KB, Parallel) at physical address 0xfff80000.
===
This flash part has status UNTESTED for operations: PROBE READ ERASE WRITE
Please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash part. Please include the flashrom
output with the additional -V option for all operations you tested (-V, -rV,
-wV, -EV), and mention which mainboard or programmer you tested.
Thanks for your help!
===
Flash image seems to be a legacy BIOS. Disabling checks.
Writing flash chip... Erasing flash chip... SUCCESS.
Programming page: DONE!ss: 0x0007f000
COMPLETE.
Verifying flash... VERIFIED.

Looked good, so I shut down the computer and it came up as normal.

Well done Michael ;-)

How do I remove the unneeded stuff from the .WHP file?

When I tried to flash with it, it gave me: Error: Image size doesn't match


2010/4/12 Michael Karcher <Michael.Karcher@fu-berlin.de>:
> Am Montag, den 12.04.2010, 00:50 +0200 schrieb Magnus Alm:
>> "sudo flashrom" doesn't cause any problems now.
> Cool, looks like I got it right.
>
>> "sudo flashrom -r BACKUP.ROM" works also tho the created file is
>> smaller than the downloaded file.
>>
>> -rw-r--r-- 1 root   root     524288 2010-04-12 00:36 BACKUP.ROM
>> -rw-r--r-- 1 magnus magnus   525894 2004-10-19 09:32 ZI5_3C23.WPH
>>
>> That might not be so strange if the downloaded file also contains
>> information about "magic bits".
> The .WPH file format contains flashing instructions appended to the
> image, while the BACKUP.ROM does not. Your backup is exactly 512*1024
> bytes big. If you want to try flashing the new image (which will most
> likely work), you should keep the data from the BACKUP.ROM at offsets
> 0x10000..0x11fff, as this 8KB area contains BIOS system information. (I
> extracted this information from the appended stuff in the .WPH file)
> The first 0xE000 bytes in your flash BIOS contain the code for the
> embedded controller.
>
> Regards,
>  Michael Karcher
>
Michael Karcher - 2010-04-12 11:31:52
Am Montag, den 12.04.2010, 02:35 +0200 schrieb Magnus Alm:
> OK, I got a problem now, tested "flashrom -EV", bad idea it seems, now
> I cant write the BACKUP.ROM back.
Oh, this looks like you *really* have a problem now. I'm sorry I didn't
think of this case beforehand, but I seriously doubt that it is possible
to fix the situation from within the running system.

The problem on your system (which carldani correctly recognized) is the
following. The data flow to the ROM chip is like

  Processor --HT--> 
  Southbridge --LPC/FWH--> 
  Embedded Controller --FWH-->
  Flash chip

The embedded controller uses parts of the flash contents as
instructions. There is one magic instruction (or two in your case) that
make the EC spin in an idle loop that doesn't access the flash chip. In
this configuration, the processor can access the flash chip as it likes
to. But this idle loop drops all EC functionality like keyboard, mouse,
fan control, brightness control, temperature monitoring and so on, so
you should only use it for limited amounts of time. When the processor
is finished with updating the flash chip, it sends a magic "exit the
idle loop" instruction to the EC.

Now, after you used flashrom -E on your flash chip, the EC program
crashes when it tries to resume. On your system, it seemed to have the
EC crashed so hard, that it doesn't pass the flash commands from the
south bridge to the flash chip. As fan control is done by EC code in
some systems, your situation might even cause overheating of the whole
system until thermal breakdown.

If your system is not damaged by heat, it is now in a configuration it
is directly after manufacturing the board - so there definitely *is* a
way to rewrite the flash chip in system, as vendors usually don't
pre-program the flash chips before assembling the board. But this way
might include special vendor tools in hardware (like test pins
contacting the board on special position) or software (like a special
protocal over JEDEC pins) we don't have.

As your system is bricked anyway now, you could open it up and try to
find the EC (a bigger chip, but not the northbridge, southbridge,
graphics chip, LAN chip or audio chip) and check whether there is a
usable datasheet for it.

> Note: flashrom can never write when the flash chip isn't found automatically.
And that is for a reason. If the flash chip is not found automatically,
it means we didn't get the probe command to the chip. In times before we
had these SPI firewalling chipsets (you don't have one), this was a
clear indication that we also can't get erase or write commands to the
chip. So erasing/writing if detection of a known chip fails is generally
futile.

I am sorry that I didn't think about the danger beforehands. I will
definitely think about a protection mechanism that prevents this
happening again before the patch goes into main flashrom.

Regards,
  Michael Karcher

Patch

diff --git a/board_enable.c b/board_enable.c
index f1f7953..ce82131 100644
--- a/board_enable.c
+++ b/board_enable.c
@@ -29,6 +29,66 @@ 
 #include "flash.h"
 
 /*
+ * Functions for EC/KBC communication
+ *  port = 0x60 for KBC, port = 0x62 (typically) for EC
+ */
+static int wait_uc_writebuf_empty(uint16_t port)
+{
+	int count;
+	for (count = 0; count < 50; count++)
+	{
+		/* quit if OBF bit clear */
+		if (!(INB(port + 4) & 2))
+			return 0;
+		usleep(10000);
+	}
+	return -1;
+}
+
+static int wait_uc_readbuf_full(uint16_t port)
+{
+	int count;
+	for (count = 0; count < 50; count++)
+	{
+		/* quit if IBF bit set */
+		if (INB(port + 4) & 1)
+			return 0;
+		usleep(10000);
+	}
+	return -1;
+}
+
+static int uc_send_command(uint16_t port, uint8_t command)
+{
+	if (wait_uc_writebuf_empty(port) != 0)
+		return -1;
+	OUTB(command, port + 4);
+	return 0;
+}
+
+#if 0
+static int uc_send_data(uint16_t port, uint8_t command)
+{
+	if (wait_uc_writebuf_empty(port) != 0)
+		return -1;
+	OUTB(command, port);
+	return 0;
+}
+#endif
+
+static int uc_read_data(uint16_t port)
+{
+	if (wait_uc_readbuf_full(port) != 0)
+		return -1;
+	return INB(port);
+}
+
+static void uc_flush_data(uint16_t port)
+{
+	INB(port);
+}
+
+/*
  * Helper functions for many Winbond Super I/Os of the W836xx range.
  */
 /* Enter extended functions */
@@ -1307,6 +1367,45 @@  static int it8712f_gpio3_1_raise(const char *name)
 	return it8712f_gpio_set(32, 1);
 }
 
+static void send_kbc_command(void * cmdptr)
+{
+	uc_send_command(0x60, *(uint8_t*)cmdptr);
+}
+
+static int board_acer_ferrari3400(const char *name)
+{
+	static uint8_t enable_command = 0xAA;
+	uint16_t pmio_base;
+	struct pci_dev * dev;
+
+	dev = pci_dev_find(0x1106, 0x3177);
+	if (!dev)
+	{
+		fprintf(stderr, "ERROR: %s - Can't find VT8235\n", name);
+		return -1;
+	}
+	pmio_base = pci_read_word(dev, 0x88) & 0xFF80;
+	if (pmio_base == 0 || pmio_base == 0xFF80)
+	{
+		fprintf(stderr, "ERROR: %s - invalid PMIO base %04x\n",
+		                name, pmio_base);
+		return -1;
+	}
+
+	usleep(100000);	/* Give the user a fair chance to release enter
+	                   before killing keyboard/mouse */
+
+        uc_flush_data(0x60);
+	register_shutdown(send_kbc_command, &enable_command);
+	if (INB(pmio_base + 4) & 1)
+		uc_send_command(0x60, 0xE5);	/* ACPI mode */
+	else
+		uc_send_command(0x60, 0xD8);	/* APM/legacy mode */
+
+	uc_read_data(0x60);		/* wait for EC shutdown */
+	return 0;
+}
+
 /**
  * Below is the list of boards which need a special "board enable" code in
  * flashrom before their ROM chip can be accessed/written to.
@@ -1356,6 +1455,7 @@  struct board_pciid_enable board_pciid_enables[] = {
 	{0x10de, 0x0050, 0x147b, 0x1c1a,       0,      0,      0,      0, NULL,          NULL,         NULL,          "Abit",        "KN8 Ultra",             0,   NT, nvidia_mcp_gpio2_lower},
 	{0x10de, 0x01e0, 0x147b, 0x1c00,  0x10de, 0x0060, 0x147B, 0x1c00, NULL,          NULL,         NULL,          "Abit",        "NF7-S",                 0,   OK, nvidia_mcp_gpio8_raise},
 	{0x1106, 0x0691,      0,      0,  0x1106, 0x3057,      0,      0, NULL,          "abit",       "vt6x4",       "Abit",        "VT6X4",                 0,   OK, via_apollo_gpo4_lower},
+	{0x1106, 0x3177, 0x1025, 0x0057,  0x1106, 0x3188, 0x1106, 0x3188, "^Ferrari 3400", NULL,       NULL,          "Acer",        "Ferrari 3400",          0,   OK, board_acer_ferrari3400},
 	{0x105a, 0x0d30, 0x105a, 0x4d33,  0x8086, 0x1130, 0x8086,      0, NULL,          NULL,         NULL,          "Acorp",       "6A815EPD",              0,   OK, board_acorp_6a815epd},
 	{0x8086, 0x24D4, 0x1849, 0x24D0,  0x8086, 0x24D5, 0x1849, 0x9739, NULL,          NULL,         NULL,          "ASRock",      "P4i65GV",               0,   OK, intel_ich_gpio23_raise},
 	{0x1022, 0x746B,      0,      0,       0,      0,      0,      0, NULL,          "AGAMI",      "ARUMA",       "agami",       "Aruma",                 0,   OK, w83627hf_gpio24_raise_2e},