blob: 4daa8c15452f39ba8fb1fd1864080dd6d60417c5 [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.
hailfingerabe249e2009-05-08 17:43:22 +000015 */
16
Edward O'Callaghanb4300ca2019-09-03 16:15:21 +100017#include <strings.h>
hailfingerabe249e2009-05-08 17:43:22 +000018#include <string.h>
19#include <stdlib.h>
hailfingerabe249e2009-05-08 17:43:22 +000020#include "flash.h"
Miriam Polzerd9785d22020-12-23 17:28:38 +010021#include "platform.h"
hailfinger428f6852010-07-27 22:41:39 +000022#include "programmer.h"
Mayur Panchalf4796862019-08-05 15:46:12 +100023#include "hwaccess.h"
hailfingerabe249e2009-05-08 17:43:22 +000024
Edward O'Callaghan48047712020-10-26 19:07:25 +110025int is_laptop = 0;
Edward O'Callaghanb902dd02021-04-23 13:33:25 +100026int laptop_ok = 0;
Edward O'Callaghan48047712020-10-26 19:07:25 +110027
28int force_boardenable = 0;
29int force_boardmismatch = 0;
30
31enum chipbustype internal_buses_supported = BUS_NONE;
32
uwe922946a2011-07-13 11:22:03 +000033struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
hailfinger07e3ce02009-11-15 17:13:29 +000034{
35 struct pci_dev *temp;
36 struct pci_filter filter;
37 uint16_t tmp2;
38
39 pci_filter_init(NULL, &filter);
40 filter.vendor = vendor;
41
42 for (temp = pacc->devices; temp; temp = temp->next)
43 if (pci_filter_match(&filter, temp)) {
44 /* Read PCI class */
45 tmp2 = pci_read_word(temp, 0x0a);
uwe922946a2011-07-13 11:22:03 +000046 if (tmp2 == devclass)
hailfinger07e3ce02009-11-15 17:13:29 +000047 return temp;
48 }
49
50 return NULL;
51}
52
hailfingerabe249e2009-05-08 17:43:22 +000053struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
54{
55 struct pci_dev *temp;
56 struct pci_filter filter;
57
58 pci_filter_init(NULL, &filter);
59 filter.vendor = vendor;
60 filter.device = device;
61
62 for (temp = pacc->devices; temp; temp = temp->next)
63 if (pci_filter_match(&filter, temp))
64 return temp;
65
66 return NULL;
67}
68
69struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
70 uint16_t card_vendor, uint16_t card_device)
71{
72 struct pci_dev *temp;
73 struct pci_filter filter;
74
75 pci_filter_init(NULL, &filter);
76 filter.vendor = vendor;
77 filter.device = device;
78
79 for (temp = pacc->devices; temp; temp = temp->next)
80 if (pci_filter_match(&filter, temp)) {
81 if ((card_vendor ==
82 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
83 && (card_device ==
84 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
85 return temp;
86 }
87
88 return NULL;
89}
90
Edward O'Callaghan6707e1e2019-08-02 23:07:15 +100091#if IS_X86
hailfingerc236f9e2009-12-22 23:42:04 +000092void probe_superio(void)
93{
Edward O'Callaghan0742c412020-10-10 15:24:46 +110094 probe_superio_winbond();
95 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
96 * Always probe for SMSC first, and if a SMSC Super I/O is detected
97 * at a given I/O port, do _not_ probe that port with the ITE probe.
98 * This means SMSC probing must be done before ITE probing.
99 */
100 //probe_superio_smsc();
hailfinger94e090c2011-04-27 14:34:08 +0000101 probe_superio_ite();
hailfingerc236f9e2009-12-22 23:42:04 +0000102}
hailfinger94e090c2011-04-27 14:34:08 +0000103
104int superio_count = 0;
105#define SUPERIO_MAX_COUNT 3
106
107struct superio superios[SUPERIO_MAX_COUNT];
108
109int register_superio(struct superio s)
110{
111 if (superio_count == SUPERIO_MAX_COUNT)
112 return 1;
113 superios[superio_count++] = s;
114 return 0;
115}
116
Edward O'Callaghanc939b722020-10-26 19:08:42 +1100117#endif /* IS_X86 */
hailfingerc236f9e2009-12-22 23:42:04 +0000118
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700119static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100120 chipaddr addr)
121{
122 mmio_writeb(val, (void *) addr);
123}
124
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700125static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100126 chipaddr addr)
127{
128 mmio_writew(val, (void *) addr);
129}
130
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700131static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100132 chipaddr addr)
133{
134 mmio_writel(val, (void *) addr);
135}
136
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700137static uint8_t internal_chip_readb(const struct flashctx *flash,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100138 const chipaddr addr)
139{
140 return mmio_readb((void *) addr);
141}
142
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700143static uint16_t internal_chip_readw(const struct flashctx *flash,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100144 const chipaddr addr)
145{
146 return mmio_readw((void *) addr);
147}
148
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700149static uint32_t internal_chip_readl(const struct flashctx *flash,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100150 const chipaddr addr)
151{
152 return mmio_readl((void *) addr);
153}
154
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700155static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
Edward O'Callaghan180503c2020-10-26 19:05:32 +1100156 const chipaddr addr, size_t len)
157{
158 mmio_readn((void *)addr, buf, len);
159 return;
160}
161
Patrick Georgi0a9533a2017-02-03 19:28:38 +0100162static const struct par_master par_master_internal = {
hailfinger76bb7e92011-11-09 23:40:00 +0000163 .chip_readb = internal_chip_readb,
164 .chip_readw = internal_chip_readw,
165 .chip_readl = internal_chip_readl,
166 .chip_readn = internal_chip_readn,
167 .chip_writeb = internal_chip_writeb,
168 .chip_writew = internal_chip_writew,
169 .chip_writel = internal_chip_writel,
170 .chip_writen = fallback_chip_writen,
171};
172
David Hendricksac1d25c2016-08-09 17:00:58 -0700173int internal_init(void)
uwebc526c82009-05-14 20:41:57 +0000174{
175 int ret = 0;
hailfingerf4aaccc2010-04-28 15:22:14 +0000176 int force_laptop = 0;
stefanct18a9eeb2011-09-13 23:14:25 +0000177 int not_a_laptop = 0;
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100178 char *board_vendor = NULL;
179 char *board_model = NULL;
Edward O'Callaghanc1867fe2020-10-10 15:44:15 +1100180#if IS_X86
Edward O'Callaghan481cce82019-05-31 15:03:50 +1000181 const char *cb_vendor = NULL;
182 const char *cb_model = NULL;
Edward O'Callaghan93c6ff82020-12-03 11:35:30 +1100183#endif
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100184 char *arg;
uwebc526c82009-05-14 20:41:57 +0000185
hailfingerddeb4ac2010-07-08 10:13:37 +0000186 arg = extract_programmer_param("boardenable");
hailfingerf4aaccc2010-04-28 15:22:14 +0000187 if (arg && !strcmp(arg,"force")) {
188 force_boardenable = 1;
189 } else if (arg && !strlen(arg)) {
190 msg_perr("Missing argument for boardenable.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000191 free(arg);
192 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000193 } else if (arg) {
194 msg_perr("Unknown argument for boardenable: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000195 free(arg);
196 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000197 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000198 free(arg);
mkarcherf2620582010-02-28 01:33:48 +0000199
hailfingerddeb4ac2010-07-08 10:13:37 +0000200 arg = extract_programmer_param("boardmismatch");
hailfingerf4aaccc2010-04-28 15:22:14 +0000201 if (arg && !strcmp(arg,"force")) {
202 force_boardmismatch = 1;
203 } else if (arg && !strlen(arg)) {
204 msg_perr("Missing argument for boardmismatch.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000205 free(arg);
206 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000207 } else if (arg) {
208 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000209 free(arg);
210 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000211 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000212 free(arg);
213
hailfingerddeb4ac2010-07-08 10:13:37 +0000214 arg = extract_programmer_param("laptop");
stefanct18a9eeb2011-09-13 23:14:25 +0000215 if (arg && !strcmp(arg, "force_I_want_a_brick"))
hailfingerf4aaccc2010-04-28 15:22:14 +0000216 force_laptop = 1;
stefanct18a9eeb2011-09-13 23:14:25 +0000217 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
218 not_a_laptop = 1;
219 else if (arg && !strlen(arg)) {
hailfingerf4aaccc2010-04-28 15:22:14 +0000220 msg_perr("Missing argument for laptop.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000221 free(arg);
222 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000223 } else if (arg) {
224 msg_perr("Unknown argument for laptop: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000225 free(arg);
226 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000227 }
228 free(arg);
229
Carl-Daniel Hailfingere5ec66e2016-08-03 16:10:19 -0700230 arg = extract_programmer_param("mainboard");
231 if (arg && strlen(arg)) {
Edward O'Callaghanf85623c2020-10-09 23:24:19 +1100232 if (board_parse_parameter(arg, &board_vendor, &board_model)) {
233 free(arg);
234 return 1;
235 }
Carl-Daniel Hailfingere5ec66e2016-08-03 16:10:19 -0700236 } else if (arg && !strlen(arg)) {
237 msg_perr("Missing argument for mainboard.\n");
238 free(arg);
239 return 1;
240 }
241 free(arg);
242
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100243 if (rget_io_perms()) {
244 ret = 1;
245 goto internal_init_exit;
246 }
hailfingerabe249e2009-05-08 17:43:22 +0000247
mkarcherd264e9e2011-05-11 17:07:07 +0000248 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
hailfinger76bb7e92011-11-09 23:40:00 +0000249 * is found, the host controller init routine sets the
250 * internal_buses_supported bitfield.
mkarcherd264e9e2011-05-11 17:07:07 +0000251 */
hailfinger76bb7e92011-11-09 23:40:00 +0000252 internal_buses_supported = BUS_NONSPI;
mkarcherd264e9e2011-05-11 17:07:07 +0000253
Edward O'Callaghan3759c822020-10-19 19:51:38 +1100254 if (try_mtd() == 0) {
255 ret = 0;
256 goto internal_init_exit;
257 }
258
259#if IS_X86
hailfingerabe249e2009-05-08 17:43:22 +0000260 /* Initialize PCI access for flash enables */
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100261 if (pci_init_common() != 0) {
262 ret = 1;
263 goto internal_init_exit;
264 }
Edward O'Callaghan004b3f22020-10-10 15:37:42 +1100265#endif // if IS_X86
hailfingerabe249e2009-05-08 17:43:22 +0000266
Paul Kocialkowski171f8082017-11-13 22:12:33 +0100267#if IS_ARM || IS_MIPS && CONFIG_LINUX_SPI == 1
Louis Yung-Chieh Loa20b3932012-05-22 22:14:00 +0800268 /* On the ARM platform, we prefer /dev/spidev if it is supported.
269 * That means, if user specifies
270 *
271 * 1. -p internal programmer
272 * 2. without -p (the default programmer, which is internal too)
273 *
274 * This code would try to auto-detect the /dev/spidevX.Y.
Simon Glassec2ea1a2013-02-10 09:41:05 -0800275 * If failed, try processor_flash_enable() then.
Louis Yung-Chieh Loa20b3932012-05-22 22:14:00 +0800276 *
277 * The -p linux_spi still works because the programmer_init() would
278 * call the linux_spi_init() in flashrom.c.
279 */
David Hendricksac1d25c2016-08-09 17:00:58 -0700280 if (!programmer_init(PROGRAMMER_LINUX_SPI, NULL)) {
Louis Yung-Chieh Loa20b3932012-05-22 22:14:00 +0800281 return 0;
282 } else /* if failed, fall through */
Edward O'Callaghan004b3f22020-10-10 15:37:42 +1100283#endif // if IS_ARM || IS_MIPS && CONFIG_LINUX_SPI == 1
hailfinger586f4ae2010-06-04 19:05:39 +0000284 if (processor_flash_enable()) {
285 msg_perr("Processor detection/init failed.\n"
286 "Aborting.\n");
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100287 ret = 1;
288 goto internal_init_exit;
hailfinger586f4ae2010-06-04 19:05:39 +0000289 }
290
Edward O'Callaghanc1867fe2020-10-10 15:44:15 +1100291#if IS_X86
Edward O'Callaghan481cce82019-05-31 15:03:50 +1000292 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
293 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
294 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
295 " match the current coreboot IDs of the mainboard (%s:%s).\n",
296 board_vendor, board_model, cb_vendor, cb_model);
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100297 if (!force_boardmismatch) {
298 ret = 1;
299 goto internal_init_exit;
300 }
Edward O'Callaghan481cce82019-05-31 15:03:50 +1000301 msg_pinfo("Continuing anyway.\n");
302 }
303 }
hailfinger324a9cc2010-05-26 01:45:41 +0000304
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000305 is_laptop = 2; /* Assume that we don't know by default. */
306
David Hendricks8e2e46e2012-09-20 22:21:54 -0700307 dmi_init();
hailfingerabe249e2009-05-08 17:43:22 +0000308
hailfingere52e9f82011-05-05 07:12:40 +0000309 /* In case Super I/O probing would cause pretty explosions. */
310 board_handle_before_superio();
311
uwef6f94d42010-03-13 17:28:29 +0000312 /* Probe for the Super I/O chip and fill global struct superio. */
hailfingerc236f9e2009-12-22 23:42:04 +0000313 probe_superio();
hailfinger586f4ae2010-06-04 19:05:39 +0000314#else
315 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
316 * by coreboot.
317 * FIXME: Find a replacement for DMI on non-x86.
318 * FIXME: Enable Super I/O probing once port I/O is possible.
319 */
Edward O'Callaghanc939b722020-10-26 19:08:42 +1100320#endif /* IS_X86 */
hailfingerc236f9e2009-12-22 23:42:04 +0000321
hailfingere52e9f82011-05-05 07:12:40 +0000322 /* Check laptop whitelist. */
323 board_handle_before_laptop();
324
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000325 /*
326 * Disable all internal buses by default if we are not sure
327 * this isn't a laptop. Board-enables may override this,
328 * non-legacy buses (SPI and opaque atm) are probed anyway.
329 */
Edward O'Callaghanb902dd02021-04-23 13:33:25 +1000330 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000331 internal_buses_supported = BUS_NONE;
mkarcher287aa242010-02-26 09:51:20 +0000332
hailfingerabe249e2009-05-08 17:43:22 +0000333 /* try to enable it. Failure IS an option, since not all motherboards
334 * really need this to be done, etc., etc.
335 */
336 ret = chipset_flash_enable();
337 if (ret == -2) {
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100338 msg_perr("WARNING: No chipset found. Flash detection "
hailfingerf4aaccc2010-04-28 15:22:14 +0000339 "will most likely fail.\n");
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100340 } else if (ret == ERROR_FATAL) {
341 goto internal_init_exit;
342 }
hailfingerabe249e2009-05-08 17:43:22 +0000343
Edward O'Callaghan0742c412020-10-10 15:24:46 +1100344#if IS_X86
345 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
346 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
347 init_superio_ite();
348
349 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
350 msg_perr("Aborting to be safe.\n");
351 ret = 1;
352 goto internal_init_exit;
353 }
Edward O'Callaghanc939b722020-10-26 19:08:42 +1100354#endif /* IS_X86 */
Edward O'Callaghan0742c412020-10-10 15:24:46 +1100355
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000356 if (internal_buses_supported & BUS_NONSPI)
357 register_par_master(&par_master_internal, internal_buses_supported);
358
359 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
360 if (is_laptop && !laptop_ok) {
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100361 msg_pinfo("========================================================================\n");
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000362 if (is_laptop == 1) {
363 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
364 "internal buses have been disabled for safety reasons.\n\n");
365 } else {
366 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100367 "detect this for sure because your vendor has not set up the SMBIOS\n"
368 "tables correctly. Some internal buses have been disabled for\n"
369 "safety reasons. You can enforce using all buses by adding\n"
370 " -p internal:laptop=this_is_not_a_laptop\n"
371 "to the command line, but please read the following warning if you\n"
372 "are not sure.\n\n");
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000373 }
374 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
375 "recommend to use the vendor flashing utility. The embedded controller\n"
376 "(EC) in these machines often interacts badly with flashing.\n"
Edward O'Callaghanb4a82892020-10-08 02:47:28 +1100377 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000378 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
379 "and write may brick your laptop.\n"
380 "Read and probe may irritate your EC and cause fan failure, backlight\n"
381 "failure and sudden poweroff.\n"
382 "You have been warned.\n"
383 "========================================================================\n");
384 }
David Hendricks3ba67132011-12-15 15:47:43 -0800385
Edward O'Callaghan392d10d2020-10-08 02:52:10 +1100386 ret = 0;
387
388internal_init_exit:
389 free(board_vendor);
390 free(board_model);
391
392 return ret;
hailfingerabe249e2009-05-08 17:43:22 +0000393}