blob: 59719d24a67243c1db0813cff6f31c28357d624f [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"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000021#include "programmer.h"
Thomas Heijligen74b4aa02021-12-14 17:52:30 +010022#include "hwaccess_physmap.h"
Thomas Heijligend96c97c2021-11-02 21:03:00 +010023#include "platform/pci.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000024
Peter Marheinedf3672d2022-01-19 17:11:09 +110025#if defined(__i386__) || defined(__x86_64__)
26#include "hwaccess_x86_io.h"
27#endif
28
Michael Karcher0bdc0922010-02-28 01:33:48 +000029int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000030int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000031
Thomas Heijligen4b918a12021-09-26 13:42:39 +020032#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000033void probe_superio(void)
34{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000035 probe_superio_winbond();
36 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
37 * Always probe for SMSC first, and if a SMSC Super I/O is detected
38 * at a given I/O port, do _not_ probe that port with the ITE probe.
39 * This means SMSC probing must be done before ITE probing.
40 */
41 //probe_superio_smsc();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +000042 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000043}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +000044
45int superio_count = 0;
46#define SUPERIO_MAX_COUNT 3
47
48struct superio superios[SUPERIO_MAX_COUNT];
49
50int register_superio(struct superio s)
51{
52 if (superio_count == SUPERIO_MAX_COUNT)
53 return 1;
54 superios[superio_count++] = s;
55 return 0;
56}
57
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000058#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000059
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000060int is_laptop = 0;
Felix Singerd1ab7d22022-08-19 03:03:47 +020061bool laptop_ok = false;
Michael Karcher8c1df282010-02-26 09:51:20 +000062
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000063static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
64 chipaddr addr);
65static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
66 chipaddr addr);
67static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
68 chipaddr addr);
69static uint8_t internal_chip_readb(const struct flashctx *flash,
70 const chipaddr addr);
71static uint16_t internal_chip_readw(const struct flashctx *flash,
72 const chipaddr addr);
73static uint32_t internal_chip_readl(const struct flashctx *flash,
74 const chipaddr addr);
75static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
76 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000077static const struct par_master par_master_internal = {
Thomas Heijligen43040f22022-06-23 14:38:35 +020078 .chip_readb = internal_chip_readb,
79 .chip_readw = internal_chip_readw,
80 .chip_readl = internal_chip_readl,
81 .chip_readn = internal_chip_readn,
82 .chip_writeb = internal_chip_writeb,
83 .chip_writew = internal_chip_writew,
84 .chip_writel = internal_chip_writel,
85 .chip_writen = fallback_chip_writen,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +000086};
87
88enum chipbustype internal_buses_supported = BUS_NONE;
89
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +110090static int get_params(int *boardenable, int *boardmismatch,
91 int *force_laptop, int *not_a_laptop,
92 char **board_vendor, char **board_model)
Uwe Hermanna0869322009-05-14 20:41:57 +000093{
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000094 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +000095
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +110096 /* default values. */
97 *force_laptop = 0;
98 *not_a_laptop = 0;
99 *board_vendor = NULL;
100 *board_model = NULL;
101
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000102 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000103 if (arg && !strcmp(arg,"force")) {
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100104 *boardenable = 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000105 } else if (arg && !strlen(arg)) {
106 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000107 free(arg);
108 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000109 } else if (arg) {
110 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000111 free(arg);
112 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000113 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000114 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000115
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000116 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000117 if (arg && !strcmp(arg,"force")) {
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100118 *boardmismatch = 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000119 } else if (arg && !strlen(arg)) {
120 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000121 free(arg);
122 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000123 } else if (arg) {
124 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000125 free(arg);
126 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000127 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000128 free(arg);
129
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000130 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000131 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100132 *force_laptop = 1;
Stefan Taunera28087f2011-09-13 23:14:25 +0000133 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100134 *not_a_laptop = 1;
Stefan Taunera28087f2011-09-13 23:14:25 +0000135 else if (arg && !strlen(arg)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000136 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000137 free(arg);
138 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000139 } else if (arg) {
140 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000141 free(arg);
142 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000143 }
144 free(arg);
145
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000146 arg = extract_programmer_param("mainboard");
147 if (arg && strlen(arg)) {
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100148 if (board_parse_parameter(arg, board_vendor, board_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000149 free(arg);
150 return 1;
151 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000152 } else if (arg && !strlen(arg)) {
153 msg_perr("Missing argument for mainboard.\n");
154 free(arg);
155 return 1;
156 }
157 free(arg);
158
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100159 return 0;
160}
161
162static int internal_init(void)
163{
164 int ret = 0;
165 int force_laptop;
166 int not_a_laptop;
167 char *board_vendor;
168 char *board_model;
169#if defined(__i386__) || defined(__x86_64__)
170 const char *cb_vendor = NULL;
171 const char *cb_model = NULL;
172#endif
173
174 ret = get_params(&force_boardenable, &force_boardmismatch,
175 &force_laptop, &not_a_laptop,
176 &board_vendor, &board_model);
177 if (ret)
178 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000179
Edward O'Callaghanbd275812022-11-28 11:20:44 +1100180 /* Unconditionally reset global state from previous operation. */
181 laptop_ok = false;
182
Michael Karcherb9dbe482011-05-11 17:07:07 +0000183 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000184 * is found, the host controller init routine sets the
185 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000186 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000187 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000188
Jacob Garber1c091d12019-08-12 11:14:14 -0600189 if (try_mtd() == 0) {
190 ret = 0;
191 goto internal_init_exit;
192 }
David Hendricksf9a30552015-05-23 20:30:30 -0700193
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000194 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600195 if (pci_init_common() != 0) {
196 ret = 1;
197 goto internal_init_exit;
198 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000199
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000200 if (processor_flash_enable()) {
201 msg_perr("Processor detection/init failed.\n"
202 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600203 ret = 1;
204 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000205 }
206
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200207#if defined(__i386__) || defined(__x86_64__)
Peter Marheinedf3672d2022-01-19 17:11:09 +1100208 if (rget_io_perms()) {
209 ret = 1;
210 goto internal_init_exit;
211 }
212
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000213 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
214 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000215 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000216 " match the current coreboot IDs of the mainboard (%s:%s).\n",
217 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600218 if (!force_boardmismatch) {
219 ret = 1;
220 goto internal_init_exit;
221 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000222 msg_pinfo("Continuing anyway.\n");
223 }
224 }
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000225
Nico Huber2e50cdc2018-09-23 20:20:26 +0200226 is_laptop = 2; /* Assume that we don't know by default. */
227
Michael Karcher6701ee82010-01-20 14:14:11 +0000228 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000229
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000230 /* In case Super I/O probing would cause pretty explosions. */
231 board_handle_before_superio();
232
Uwe Hermann43959702010-03-13 17:28:29 +0000233 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000234 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000235#else
236 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
237 * by coreboot.
238 * FIXME: Find a replacement for DMI on non-x86.
239 * FIXME: Enable Super I/O probing once port I/O is possible.
240 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000241#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000242
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000243 /* Check laptop whitelist. */
244 board_handle_before_laptop();
245
Nico Huber2e50cdc2018-09-23 20:20:26 +0200246 /*
247 * Disable all internal buses by default if we are not sure
248 * this isn't a laptop. Board-enables may override this,
249 * non-legacy buses (SPI and opaque atm) are probed anyway.
250 */
251 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
252 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000253
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000254 /* try to enable it. Failure IS an option, since not all motherboards
255 * really need this to be done, etc., etc.
256 */
257 ret = chipset_flash_enable();
258 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000259 msg_perr("WARNING: No chipset found. Flash detection "
260 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600261 } else if (ret == ERROR_FATAL) {
262 goto internal_init_exit;
263 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000264
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200265#if defined(__i386__) || defined(__x86_64__)
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000266 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
267 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000268 init_superio_ite();
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000269
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000270 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000271 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600272 ret = 1;
273 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000274 }
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000275#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000276
Nico Huber2e50cdc2018-09-23 20:20:26 +0200277 if (internal_buses_supported & BUS_NONSPI)
Anastasia Klimchukb91a2032021-05-21 09:40:58 +1000278 register_par_master(&par_master_internal, internal_buses_supported, NULL);
Nico Huber2e50cdc2018-09-23 20:20:26 +0200279
280 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
281 if (is_laptop && !laptop_ok) {
282 msg_pinfo("========================================================================\n");
283 if (is_laptop == 1) {
284 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
285 "internal buses have been disabled for safety reasons.\n\n");
286 } else {
287 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
288 "detect this for sure because your vendor has not set up the SMBIOS\n"
289 "tables correctly. Some internal buses have been disabled for\n"
290 "safety reasons. You can enforce using all buses by adding\n"
291 " -p internal:laptop=this_is_not_a_laptop\n"
292 "to the command line, but please read the following warning if you\n"
293 "are not sure.\n\n");
294 }
295 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
296 "recommend to use the vendor flashing utility. The embedded controller\n"
297 "(EC) in these machines often interacts badly with flashing.\n"
298 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
299 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
300 "and write may brick your laptop.\n"
301 "Read and probe may irritate your EC and cause fan failure, backlight\n"
302 "failure and sudden poweroff.\n"
303 "You have been warned.\n"
304 "========================================================================\n");
305 }
306
Jacob Garber1c091d12019-08-12 11:14:14 -0600307 ret = 0;
308
309internal_init_exit:
310 free(board_vendor);
311 free(board_model);
312
313 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000314}
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000315
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000316static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
317 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000318{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000319 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000320}
321
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000322static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
323 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000324{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000325 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000326}
327
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000328static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
329 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000330{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000331 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000332}
333
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000334static uint8_t internal_chip_readb(const struct flashctx *flash,
335 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000336{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000337 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000338}
339
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000340static uint16_t internal_chip_readw(const struct flashctx *flash,
341 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000342{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000343 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000344}
345
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000346static uint32_t internal_chip_readl(const struct flashctx *flash,
347 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000348{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000349 return mmio_readl((void *) addr);
350}
351
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000352static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
353 const chipaddr addr, size_t len)
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000354{
Carl-Daniel Hailfingerccd71c22012-03-01 22:38:27 +0000355 mmio_readn((void *)addr, buf, len);
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000356 return;
357}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200358
359const struct programmer_entry programmer_internal = {
360 .name = "internal",
361 .type = OTHER,
362 .devs.note = NULL,
363 .init = internal_init,
364 .map_flash_region = physmap,
365 .unmap_flash_region = physunmap,
366 .delay = internal_delay,
367};