blob: e38b6d5beb16518f1e3d3c25e9d9d01137d7347e [file] [log] [blame]
hailfingerabe249e2009-05-08 17:43:22 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
David Hendricks39a32412011-03-24 17:14:01 -070021#include <stdio.h>
hailfingerabe249e2009-05-08 17:43:22 +000022#include <string.h>
23#include <stdlib.h>
David Hendricks39a32412011-03-24 17:14:01 -070024#include <stdarg.h>
hailfingerabe249e2009-05-08 17:43:22 +000025#include "flash.h"
hailfinger428f6852010-07-27 22:41:39 +000026#include "programmer.h"
hailfingerabe249e2009-05-08 17:43:22 +000027
hailfinger80422e22009-12-13 22:28:00 +000028#if NEED_PCI == 1
uwe6934c4a2009-05-14 18:57:26 +000029struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
30{
31 struct pci_dev *temp;
32
33 for (temp = pacc->devices; temp; temp = temp->next)
34 if (pci_filter_match(&filter, temp))
35 return temp;
36
37 return NULL;
38}
39
uwe922946a2011-07-13 11:22:03 +000040struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
hailfinger07e3ce02009-11-15 17:13:29 +000041{
42 struct pci_dev *temp;
43 struct pci_filter filter;
44 uint16_t tmp2;
45
46 pci_filter_init(NULL, &filter);
47 filter.vendor = vendor;
48
49 for (temp = pacc->devices; temp; temp = temp->next)
50 if (pci_filter_match(&filter, temp)) {
51 /* Read PCI class */
52 tmp2 = pci_read_word(temp, 0x0a);
uwe922946a2011-07-13 11:22:03 +000053 if (tmp2 == devclass)
hailfinger07e3ce02009-11-15 17:13:29 +000054 return temp;
55 }
56
57 return NULL;
58}
59
hailfingerabe249e2009-05-08 17:43:22 +000060struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
61{
62 struct pci_dev *temp;
63 struct pci_filter filter;
64
65 pci_filter_init(NULL, &filter);
66 filter.vendor = vendor;
67 filter.device = device;
68
69 for (temp = pacc->devices; temp; temp = temp->next)
70 if (pci_filter_match(&filter, temp))
71 return temp;
72
73 return NULL;
74}
75
76struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
77 uint16_t card_vendor, uint16_t card_device)
78{
79 struct pci_dev *temp;
80 struct pci_filter filter;
81
82 pci_filter_init(NULL, &filter);
83 filter.vendor = vendor;
84 filter.device = device;
85
86 for (temp = pacc->devices; temp; temp = temp->next)
87 if (pci_filter_match(&filter, temp)) {
88 if ((card_vendor ==
89 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
90 && (card_device ==
91 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
92 return temp;
93 }
94
95 return NULL;
96}
hailfinger80422e22009-12-13 22:28:00 +000097#endif
hailfingerabe249e2009-05-08 17:43:22 +000098
hailfinger90c7d542010-05-31 15:27:27 +000099#if CONFIG_INTERNAL == 1
mkarcherf2620582010-02-28 01:33:48 +0000100int force_boardenable = 0;
hailfingerf4aaccc2010-04-28 15:22:14 +0000101int force_boardmismatch = 0;
hailfingerc236f9e2009-12-22 23:42:04 +0000102
hailfinger324a9cc2010-05-26 01:45:41 +0000103#if defined(__i386__) || defined(__x86_64__)
hailfingerc236f9e2009-12-22 23:42:04 +0000104void probe_superio(void)
105{
hailfinger94e090c2011-04-27 14:34:08 +0000106 probe_superio_ite();
uwef6f94d42010-03-13 17:28:29 +0000107#if 0
108 /* Winbond Super I/O code is not yet available. */
hailfingerc236f9e2009-12-22 23:42:04 +0000109 if (superio.vendor == SUPERIO_VENDOR_NONE)
110 superio = probe_superio_winbond();
111#endif
112}
hailfinger94e090c2011-04-27 14:34:08 +0000113
114int superio_count = 0;
115#define SUPERIO_MAX_COUNT 3
116
117struct superio superios[SUPERIO_MAX_COUNT];
118
119int register_superio(struct superio s)
120{
121 if (superio_count == SUPERIO_MAX_COUNT)
122 return 1;
123 superios[superio_count++] = s;
124 return 0;
125}
126
hailfinger324a9cc2010-05-26 01:45:41 +0000127#endif
hailfingerc236f9e2009-12-22 23:42:04 +0000128
hailfinger324a9cc2010-05-26 01:45:41 +0000129int is_laptop = 0;
hailfingere52e9f82011-05-05 07:12:40 +0000130int laptop_ok = 0;
mkarcher287aa242010-02-26 09:51:20 +0000131
dhendrix0ffc2eb2011-06-14 01:35:36 +0000132static int internal_shutdown(void *data)
133{
134 release_io_perms();
135 return 0;
136}
David Hendricks80f62d22010-10-08 11:09:35 -0700137enum chipbustype target_bus;
hailfinger80422e22009-12-13 22:28:00 +0000138
David Hendricks6fae52e2011-03-24 18:50:18 -0700139#if NEED_PCI == 1
David Hendricks39a32412011-03-24 17:14:01 -0700140#define BUFSIZE 256
141static char buffer[BUFSIZE];
142
143static void
144pci_error(char *msg, ...)
145{
146 va_list args;
147
148 va_start(args, msg);
149 vsnprintf(buffer, BUFSIZE, msg, args);
150 va_end(args);
151
152 msg_perr("pcilib: %s\n", buffer);
153
154 /* libpci requires us to exit. TODO cleanup? */
155 exit(1);
156}
157
158static void
159pci_warning(char *msg, ...)
160{
161 va_list args;
162
163 va_start(args, msg);
164 vsnprintf(buffer, BUFSIZE, msg, args);
165 va_end(args);
166
167 msg_pinfo("pcilib: %s\n", buffer);
168}
169
170static void
171pci_debug(char *msg, ...)
172{
173 va_list args;
174
175 va_start(args, msg);
176 vsnprintf(buffer, BUFSIZE, msg, args);
177 va_end(args);
178
179 msg_pdbg("pcilib: %s\n", buffer);
180}
181#endif
dhendrix0ffc2eb2011-06-14 01:35:36 +0000182
uwebc526c82009-05-14 20:41:57 +0000183int internal_init(void)
184{
uweca168f82010-09-20 17:23:38 +0000185#if __FLASHROM_LITTLE_ENDIAN__
uwebc526c82009-05-14 20:41:57 +0000186 int ret = 0;
uweca168f82010-09-20 17:23:38 +0000187#endif
hailfingerf4aaccc2010-04-28 15:22:14 +0000188 int force_laptop = 0;
stefanct18a9eeb2011-09-13 23:14:25 +0000189 int not_a_laptop = 0;
hailfingerf4aaccc2010-04-28 15:22:14 +0000190 char *arg;
Louis Yung-Chieh Lo6b8f0462011-01-06 12:49:46 +0800191 int probe_target_bus_later = 0;
uwebc526c82009-05-14 20:41:57 +0000192
hailfingerddeb4ac2010-07-08 10:13:37 +0000193 arg = extract_programmer_param("boardenable");
hailfingerf4aaccc2010-04-28 15:22:14 +0000194 if (arg && !strcmp(arg,"force")) {
195 force_boardenable = 1;
196 } else if (arg && !strlen(arg)) {
197 msg_perr("Missing argument for boardenable.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000198 free(arg);
199 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000200 } else if (arg) {
201 msg_perr("Unknown argument for boardenable: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000202 free(arg);
203 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000204 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000205 free(arg);
mkarcherf2620582010-02-28 01:33:48 +0000206
hailfingerddeb4ac2010-07-08 10:13:37 +0000207 arg = extract_programmer_param("boardmismatch");
hailfingerf4aaccc2010-04-28 15:22:14 +0000208 if (arg && !strcmp(arg,"force")) {
209 force_boardmismatch = 1;
210 } else if (arg && !strlen(arg)) {
211 msg_perr("Missing argument for boardmismatch.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000212 free(arg);
213 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000214 } else if (arg) {
215 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000216 free(arg);
217 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000218 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000219 free(arg);
220
hailfingerddeb4ac2010-07-08 10:13:37 +0000221 arg = extract_programmer_param("laptop");
stefanct18a9eeb2011-09-13 23:14:25 +0000222 if (arg && !strcmp(arg, "force_I_want_a_brick"))
hailfingerf4aaccc2010-04-28 15:22:14 +0000223 force_laptop = 1;
stefanct18a9eeb2011-09-13 23:14:25 +0000224 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
225 not_a_laptop = 1;
226 else if (arg && !strlen(arg)) {
hailfingerf4aaccc2010-04-28 15:22:14 +0000227 msg_perr("Missing argument for laptop.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000228 free(arg);
229 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000230 } else if (arg) {
231 msg_perr("Unknown argument for laptop: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000232 free(arg);
233 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000234 }
235 free(arg);
236
David Hendricks80f62d22010-10-08 11:09:35 -0700237 arg = extract_programmer_param("bus");
238 if (arg) {
239 if (!strcasecmp(arg,"parallel")) {
hailfingere1e41ea2011-07-27 07:13:06 +0000240 target_bus = BUS_PARALLEL;
David Hendricks80f62d22010-10-08 11:09:35 -0700241 } else if (!strcasecmp(arg,"lpc")) {
hailfingere1e41ea2011-07-27 07:13:06 +0000242 target_bus = BUS_LPC;
David Hendricks80f62d22010-10-08 11:09:35 -0700243 } else if (!strcasecmp(arg,"fwh")) {
hailfingere1e41ea2011-07-27 07:13:06 +0000244 target_bus = BUS_FWH;
David Hendricks80f62d22010-10-08 11:09:35 -0700245 } else if (!strcasecmp(arg,"spi")) {
hailfingere1e41ea2011-07-27 07:13:06 +0000246 target_bus = BUS_SPI;
David Hendricks80f62d22010-10-08 11:09:35 -0700247 } else {
David Hendricks80f62d22010-10-08 11:09:35 -0700248 free(arg);
249 return 1;
250 }
251
252 free(arg);
Louis Yung-Chieh Lo6b8f0462011-01-06 12:49:46 +0800253 } else {
254 /* The pacc must be initialized before access pci devices. */
255 probe_target_bus_later = 1;
David Hendricks80f62d22010-10-08 11:09:35 -0700256 }
257
hailfinger0668eba2009-05-14 21:41:10 +0000258 get_io_perms();
dhendrix0ffc2eb2011-06-14 01:35:36 +0000259 if (register_shutdown(internal_shutdown, NULL))
260 return 1;
hailfingerabe249e2009-05-08 17:43:22 +0000261
mkarcherd264e9e2011-05-11 17:07:07 +0000262 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
263 * is found, the init routine sets the buses_supported bitfield.
264 */
hailfingere1e41ea2011-07-27 07:13:06 +0000265 buses_supported = BUS_NONSPI;
mkarcherd264e9e2011-05-11 17:07:07 +0000266
David Hendrickscb2cec32011-03-24 18:44:49 -0700267#if defined(__i386__) || defined(__x86_64__)
hailfingerabe249e2009-05-08 17:43:22 +0000268 /* Initialize PCI access for flash enables */
269 pacc = pci_alloc(); /* Get the pci_access structure */
David Hendricks39a32412011-03-24 17:14:01 -0700270 pacc->error = pci_error;
271 pacc->warning = pci_warning;
272 pacc->debug = pci_debug;
273
hailfingerabe249e2009-05-08 17:43:22 +0000274 /* Set all options you want -- here we stick with the defaults */
275 pci_init(pacc); /* Initialize the PCI library */
276 pci_scan_bus(pacc); /* We want to get the list of devices */
David Hendrickscb2cec32011-03-24 18:44:49 -0700277#endif
hailfingerabe249e2009-05-08 17:43:22 +0000278
hailfinger586f4ae2010-06-04 19:05:39 +0000279 if (processor_flash_enable()) {
280 msg_perr("Processor detection/init failed.\n"
281 "Aborting.\n");
282 return 1;
283 }
284
285#if defined(__i386__) || defined(__x86_64__)
286 /* We look at the cbtable first to see if we need a
hailfingerabe249e2009-05-08 17:43:22 +0000287 * mainboard specific flash enable sequence.
288 */
289 coreboot_init();
hailfinger324a9cc2010-05-26 01:45:41 +0000290
David Hendricks8e806e62011-07-12 16:45:59 -0700291 /* FIXME: Removed to avoid annoying laptop warnings */
292 //dmi_init();
hailfingerabe249e2009-05-08 17:43:22 +0000293
Louis Yung-Chieh Lo6b8f0462011-01-06 12:49:46 +0800294 if (probe_target_bus_later) {
295 /* read the target bus value from register. */
296 if (get_target_bus_from_chipset(&target_bus)) {
hailfinger969e2f32011-09-08 00:00:29 +0000297 msg_perr("Cannot get target bus from programmer.\n");
Louis Yung-Chieh Lo6b8f0462011-01-06 12:49:46 +0800298 return 1;
299 }
Louis Yung-Chieh Lo8381f152011-10-31 15:45:04 +0800300 msg_pdbg("get_target_bus_from_chipset() returns 0x%x.\n",
301 target_bus);
Louis Yung-Chieh Lo6b8f0462011-01-06 12:49:46 +0800302 }
303
hailfingere52e9f82011-05-05 07:12:40 +0000304 /* In case Super I/O probing would cause pretty explosions. */
305 board_handle_before_superio();
306
uwef6f94d42010-03-13 17:28:29 +0000307 /* Probe for the Super I/O chip and fill global struct superio. */
hailfingerc236f9e2009-12-22 23:42:04 +0000308 probe_superio();
David Hendrickscf239a82011-03-24 19:06:23 -0700309
310#elif defined(__arm__)
311 /* We look at the cbtable first to see if we need a
312 * mainboard specific flash enable sequence.
313 */
314 coreboot_init();
315
hailfinger586f4ae2010-06-04 19:05:39 +0000316#else
317 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
318 * by coreboot.
319 * FIXME: Find a replacement for DMI on non-x86.
320 * FIXME: Enable Super I/O probing once port I/O is possible.
321 */
hailfinger324a9cc2010-05-26 01:45:41 +0000322#endif
hailfingerc236f9e2009-12-22 23:42:04 +0000323
hailfingere52e9f82011-05-05 07:12:40 +0000324 /* Check laptop whitelist. */
325 board_handle_before_laptop();
326
327 /* Warn if a non-whitelisted laptop is detected. */
328 if (is_laptop && !laptop_ok) {
stefanct674e81e2011-07-26 00:54:42 +0000329 msg_perr("========================================================================\n");
330 if (is_laptop == 1) {
331 msg_perr("WARNING! You seem to be running flashrom on an unsupported laptop.\n");
332 } else {
333 msg_perr("WARNING! You may be running flashrom on an unsupported laptop. We could\n"
334 "not detect this for sure because your vendor has not setup the SMBIOS\n"
335 "tables correctly. You can enforce execution by adding\n"
stefanct18a9eeb2011-09-13 23:14:25 +0000336 "'-p internal:laptop=this_is_not_a_laptop' to the command line, but\n"
stefanct674e81e2011-07-26 00:54:42 +0000337 "please read the following warning if you are not sure.\n\n");
338 }
339 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
340 "recommend to use the vendor flashing utility. The embedded controller\n"
341 "(EC) in these machines often interacts badly with flashing.\n"
hailfingerf4aaccc2010-04-28 15:22:14 +0000342 "See http://www.flashrom.org/Laptops for details.\n\n"
343 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
344 "and write may brick your laptop.\n"
345 "Read and probe may irritate your EC and cause fan failure, backlight\n"
346 "failure and sudden poweroff.\n"
347 "You have been warned.\n"
348 "========================================================================\n");
stefanct674e81e2011-07-26 00:54:42 +0000349
stefanct18a9eeb2011-09-13 23:14:25 +0000350 if (force_laptop || (not_a_laptop && (is_laptop == 2))) {
351 msg_perr("Proceeding anyway because user forced us to.\n");
hailfingerf4aaccc2010-04-28 15:22:14 +0000352 } else {
353 msg_perr("Aborting.\n");
354 exit(1);
355 }
356 }
mkarcher287aa242010-02-26 09:51:20 +0000357
hailfinger586f4ae2010-06-04 19:05:39 +0000358#if __FLASHROM_LITTLE_ENDIAN__
David Hendricks351c9962011-03-25 11:44:35 -0700359#if defined(__i386__) || defined(__x86_64__) || defined (__mips__)
hailfingerabe249e2009-05-08 17:43:22 +0000360 /* try to enable it. Failure IS an option, since not all motherboards
361 * really need this to be done, etc., etc.
362 */
363 ret = chipset_flash_enable();
364 if (ret == -2) {
hailfingerf4aaccc2010-04-28 15:22:14 +0000365 msg_perr("WARNING: No chipset found. Flash detection "
366 "will most likely fail.\n");
uwe97e8e272011-09-03 17:15:00 +0000367 } else if (ret == ERROR_FATAL)
368 return ret;
David Hendricks351c9962011-03-25 11:44:35 -0700369#endif
hailfingerabe249e2009-05-08 17:43:22 +0000370
hailfinger324a9cc2010-05-26 01:45:41 +0000371#if defined(__i386__) || defined(__x86_64__)
hailfingerc73ce6e2010-07-10 16:56:32 +0000372 /* Probe unconditionally for IT87* LPC->SPI translation and for
373 * IT87* Parallel write enable.
374 */
375 init_superio_ite();
David Hendricksc801adb2010-12-09 16:58:56 -0800376
David Hendrickse18bbc62010-12-28 17:50:05 -0800377 /* probe for programmers that bridge LPC <--> SPI */
hailfingere1e41ea2011-07-27 07:13:06 +0000378 if (target_bus == BUS_LPC ||
379 target_bus == BUS_FWH) {
David Hendricks91040832011-07-08 20:01:09 -0700380 /* note: it85xx init done along with it87* init */
David Hendrickse18bbc62010-12-28 17:50:05 -0800381 wpce775x_probe_spi_flash(NULL);
David Hendricks46d32e32011-01-19 16:01:52 -0800382 mec1308_probe_spi_flash(NULL);
David Hendrickse18bbc62010-12-28 17:50:05 -0800383 }
384
hailfinger324a9cc2010-05-26 01:45:41 +0000385#endif
hailfingerddd5d7b2010-03-25 02:50:40 +0000386
hailfingerabe249e2009-05-08 17:43:22 +0000387 board_flash_enable(lb_vendor, lb_part);
388
hailfinger681638b2009-09-02 13:43:56 +0000389 /* Even if chipset init returns an error code, we don't want to abort.
390 * The error code might have been a warning only.
391 * Besides that, we don't check the board enable return code either.
392 */
David Hendrickscf239a82011-03-24 19:06:23 -0700393#if defined(__i386__) || defined(__x86_64__) || defined (__mips) || defined (__arm__)
hailfingerf4aaccc2010-04-28 15:22:14 +0000394 return 0;
hailfinger586f4ae2010-06-04 19:05:39 +0000395#else
396 msg_perr("Your platform is not supported yet for the internal "
397 "programmer due to missing\n"
398 "flash_base and top/bottom alignment information.\n"
399 "Aborting.\n");
400 return 1;
401#endif
402#else
403 /* FIXME: Remove this unconditional abort once all PCI drivers are
404 * converted to use little-endian accesses for memory BARs.
405 */
406 msg_perr("Your platform is not supported yet for the internal "
407 "programmer because it has\n"
408 "not been converted from native endian to little endian "
409 "access yet.\n"
410 "Aborting.\n");
411 return 1;
412#endif
hailfingerabe249e2009-05-08 17:43:22 +0000413}
hailfinger80422e22009-12-13 22:28:00 +0000414#endif
hailfingerabe249e2009-05-08 17:43:22 +0000415
hailfinger82719632009-05-16 21:22:56 +0000416void internal_chip_writeb(uint8_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000417{
hailfinger38da6812009-05-17 15:49:24 +0000418 mmio_writeb(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000419}
420
hailfinger82719632009-05-16 21:22:56 +0000421void internal_chip_writew(uint16_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000422{
hailfinger38da6812009-05-17 15:49:24 +0000423 mmio_writew(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000424}
425
hailfinger82719632009-05-16 21:22:56 +0000426void internal_chip_writel(uint32_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000427{
hailfinger38da6812009-05-17 15:49:24 +0000428 mmio_writel(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000429}
430
hailfinger82719632009-05-16 21:22:56 +0000431uint8_t internal_chip_readb(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000432{
hailfinger38da6812009-05-17 15:49:24 +0000433 return mmio_readb((void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000434}
435
hailfinger82719632009-05-16 21:22:56 +0000436uint16_t internal_chip_readw(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000437{
hailfinger38da6812009-05-17 15:49:24 +0000438 return mmio_readw((void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000439}
440
hailfinger82719632009-05-16 21:22:56 +0000441uint32_t internal_chip_readl(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000442{
hailfinger38da6812009-05-17 15:49:24 +0000443 return mmio_readl((void *) addr);
444}
445
hailfinger9d987ef2009-06-05 18:32:07 +0000446void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
447{
448 memcpy(buf, (void *)addr, len);
449 return;
450}