blob: abd4637aa2befceba1d4ec56ed74c34f6b05162c [file] [log] [blame]
Carl-Daniel Hailfinger702218d2009-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.
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000015 */
16
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +000017#include <strings.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000018#include <string.h>
19#include <stdlib.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000020#include "flash.h"
Miriam Polzer5ab46562020-12-23 17:28:38 +010021#include "platform.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000022#include "programmer.h"
Patrick Georgi32508eb2012-07-20 20:35:14 +000023#include "hwaccess.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000024
Edward O'Callaghanc15de252020-10-26 19:07:25 +110025int is_laptop = 0;
26int laptop_ok = 0;
27
28int force_boardenable = 0;
29int force_boardmismatch = 0;
30
31enum chipbustype internal_buses_supported = BUS_NONE;
32
Uwe Hermann24c35e42011-07-13 11:22:03 +000033struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
Carl-Daniel Hailfinger9f46cfc2009-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);
Uwe Hermann24c35e42011-07-13 11:22:03 +000046 if (tmp2 == devclass)
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000047 return temp;
48 }
49
50 return NULL;
51}
52
Carl-Daniel Hailfinger702218d2009-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
Nico Huberc8801732017-12-01 18:19:43 +000091#if IS_X86
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000092void probe_superio(void)
93{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000094 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();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000101 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000102}
Carl-Daniel Hailfingerbfecef62011-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'Callaghan74fd0302020-10-26 19:08:42 +1100117#endif /* IS_X86 */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000118
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000119static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100120 chipaddr addr)
121{
122 mmio_writeb(val, (void *) addr);
123}
124
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000125static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100126 chipaddr addr)
127{
128 mmio_writew(val, (void *) addr);
129}
130
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000131static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100132 chipaddr addr)
133{
134 mmio_writel(val, (void *) addr);
135}
136
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000137static uint8_t internal_chip_readb(const struct flashctx *flash,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100138 const chipaddr addr)
139{
140 return mmio_readb((void *) addr);
141}
142
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000143static uint16_t internal_chip_readw(const struct flashctx *flash,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100144 const chipaddr addr)
145{
146 return mmio_readw((void *) addr);
147}
148
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000149static uint32_t internal_chip_readl(const struct flashctx *flash,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100150 const chipaddr addr)
151{
152 return mmio_readl((void *) addr);
153}
154
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000155static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
Edward O'Callaghand7b48752020-10-26 19:05:32 +1100156 const chipaddr addr, size_t len)
157{
158 mmio_readn((void *)addr, buf, len);
159 return;
160}
161
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000162static const struct par_master par_master_internal = {
Carl-Daniel Hailfingereaacd2d2011-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
Thomas Heijligen4f5169d2021-05-04 15:32:17 +0200173static int internal_init(void)
Uwe Hermanna0869322009-05-14 20:41:57 +0000174{
175 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000176 int force_laptop = 0;
Stefan Taunera28087f2011-09-13 23:14:25 +0000177 int not_a_laptop = 0;
Jacob Garber1c091d12019-08-12 11:14:14 -0600178 char *board_vendor = NULL;
179 char *board_model = NULL;
Nico Huberc8801732017-12-01 18:19:43 +0000180#if IS_X86
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000181 const char *cb_vendor = NULL;
182 const char *cb_model = NULL;
Carl-Daniel Hailfinger11990da2013-07-13 23:21:05 +0000183#endif
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000184 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000185
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000186 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-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");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000191 free(arg);
192 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000193 } else if (arg) {
194 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000195 free(arg);
196 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000197 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000198 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000199
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000200 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-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");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000205 free(arg);
206 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000207 } else if (arg) {
208 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000209 free(arg);
210 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000211 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000212 free(arg);
213
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000214 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000215 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000216 force_laptop = 1;
Stefan Taunera28087f2011-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)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000220 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000221 free(arg);
222 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000223 } else if (arg) {
224 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000225 free(arg);
226 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000227 }
228 free(arg);
229
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000230 arg = extract_programmer_param("mainboard");
231 if (arg && strlen(arg)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000232 if (board_parse_parameter(arg, &board_vendor, &board_model)) {
233 free(arg);
234 return 1;
235 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000236 } else if (arg && !strlen(arg)) {
237 msg_perr("Missing argument for mainboard.\n");
238 free(arg);
239 return 1;
240 }
241 free(arg);
242
Jacob Garber1c091d12019-08-12 11:14:14 -0600243 if (rget_io_perms()) {
244 ret = 1;
245 goto internal_init_exit;
246 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000247
Michael Karcherb9dbe482011-05-11 17:07:07 +0000248 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000249 * is found, the host controller init routine sets the
250 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000251 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000252 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000253
Jacob Garber1c091d12019-08-12 11:14:14 -0600254 if (try_mtd() == 0) {
255 ret = 0;
256 goto internal_init_exit;
257 }
David Hendricksf9a30552015-05-23 20:30:30 -0700258
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000259 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600260 if (pci_init_common() != 0) {
261 ret = 1;
262 goto internal_init_exit;
263 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000264
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000265 if (processor_flash_enable()) {
266 msg_perr("Processor detection/init failed.\n"
267 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600268 ret = 1;
269 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000270 }
271
Nico Huberc8801732017-12-01 18:19:43 +0000272#if IS_X86
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000273 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
274 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000275 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000276 " match the current coreboot IDs of the mainboard (%s:%s).\n",
277 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600278 if (!force_boardmismatch) {
279 ret = 1;
280 goto internal_init_exit;
281 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000282 msg_pinfo("Continuing anyway.\n");
283 }
284 }
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000285
Nico Huber2e50cdc2018-09-23 20:20:26 +0200286 is_laptop = 2; /* Assume that we don't know by default. */
287
Michael Karcher6701ee82010-01-20 14:14:11 +0000288 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000289
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000290 /* In case Super I/O probing would cause pretty explosions. */
291 board_handle_before_superio();
292
Uwe Hermann43959702010-03-13 17:28:29 +0000293 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000294 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000295#else
296 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
297 * by coreboot.
298 * FIXME: Find a replacement for DMI on non-x86.
299 * FIXME: Enable Super I/O probing once port I/O is possible.
300 */
Edward O'Callaghan74fd0302020-10-26 19:08:42 +1100301#endif /* IS_X86 */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000302
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000303 /* Check laptop whitelist. */
304 board_handle_before_laptop();
305
Nico Huber2e50cdc2018-09-23 20:20:26 +0200306 /*
307 * Disable all internal buses by default if we are not sure
308 * this isn't a laptop. Board-enables may override this,
309 * non-legacy buses (SPI and opaque atm) are probed anyway.
310 */
311 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
312 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000313
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000314 /* try to enable it. Failure IS an option, since not all motherboards
315 * really need this to be done, etc., etc.
316 */
317 ret = chipset_flash_enable();
318 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000319 msg_perr("WARNING: No chipset found. Flash detection "
320 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600321 } else if (ret == ERROR_FATAL) {
322 goto internal_init_exit;
323 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000324
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000325#if IS_X86
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000326 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
327 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000328 init_superio_ite();
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000329
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000330 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000331 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600332 ret = 1;
333 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000334 }
Edward O'Callaghan74fd0302020-10-26 19:08:42 +1100335#endif /* IS_X86 */
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000336
Nico Huber2e50cdc2018-09-23 20:20:26 +0200337 if (internal_buses_supported & BUS_NONSPI)
Anastasia Klimchuk6a5db262021-05-21 09:40:58 +1000338 register_par_master(&par_master_internal, internal_buses_supported, NULL);
Nico Huber2e50cdc2018-09-23 20:20:26 +0200339
340 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
341 if (is_laptop && !laptop_ok) {
342 msg_pinfo("========================================================================\n");
343 if (is_laptop == 1) {
344 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
345 "internal buses have been disabled for safety reasons.\n\n");
346 } else {
347 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
348 "detect this for sure because your vendor has not set up the SMBIOS\n"
349 "tables correctly. Some internal buses have been disabled for\n"
350 "safety reasons. You can enforce using all buses by adding\n"
351 " -p internal:laptop=this_is_not_a_laptop\n"
352 "to the command line, but please read the following warning if you\n"
353 "are not sure.\n\n");
354 }
355 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
356 "recommend to use the vendor flashing utility. The embedded controller\n"
357 "(EC) in these machines often interacts badly with flashing.\n"
358 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
359 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
360 "and write may brick your laptop.\n"
361 "Read and probe may irritate your EC and cause fan failure, backlight\n"
362 "failure and sudden poweroff.\n"
363 "You have been warned.\n"
364 "========================================================================\n");
365 }
366
Jacob Garber1c091d12019-08-12 11:14:14 -0600367 ret = 0;
368
369internal_init_exit:
370 free(board_vendor);
371 free(board_model);
372
373 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000374}
Thomas Heijligen4f5169d2021-05-04 15:32:17 +0200375
376const struct programmer_entry programmer_internal = {
377 .name = "internal",
378 .type = OTHER,
379 .devs.note = NULL,
380 .init = internal_init,
381 .map_flash_region = physmap,
382 .unmap_flash_region = physunmap,
383 .delay = internal_delay,
384};