blob: 7f9713a1c718e05ac13944b95a2da042acb531cf [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>
Felix Singerb8db74a2022-08-19 00:19:26 +020019#include <stdbool.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000020#include <stdlib.h>
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000021#include "programmer.h"
Nico Huber239dc802026-06-24 23:04:58 +020022#include "programmer/physmap.h"
Thomas Heijligen74b4aa02021-12-14 17:52:30 +010023#include "hwaccess_physmap.h"
Thomas Heijligend96c97c2021-11-02 21:03:00 +010024#include "platform/pci.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000025
Peter Marheinedf3672d2022-01-19 17:11:09 +110026#if defined(__i386__) || defined(__x86_64__)
27#include "hwaccess_x86_io.h"
28#endif
29
Felix Singerb8db74a2022-08-19 00:19:26 +020030bool force_boardenable = false;
31bool force_boardmismatch = false;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000032
Thomas Heijligen4b918a12021-09-26 13:42:39 +020033#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000034void probe_superio(void)
35{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000036 probe_superio_winbond();
37 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
38 * Always probe for SMSC first, and if a SMSC Super I/O is detected
39 * at a given I/O port, do _not_ probe that port with the ITE probe.
40 * This means SMSC probing must be done before ITE probing.
41 */
42 //probe_superio_smsc();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +000043 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000044}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +000045
46int superio_count = 0;
47#define SUPERIO_MAX_COUNT 3
48
49struct superio superios[SUPERIO_MAX_COUNT];
50
51int register_superio(struct superio s)
52{
53 if (superio_count == SUPERIO_MAX_COUNT)
54 return 1;
55 superios[superio_count++] = s;
56 return 0;
57}
58
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000059#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000060
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000061int is_laptop = 0;
Felix Singerd1ab7d22022-08-19 03:03:47 +020062bool laptop_ok = false;
Michael Karcher8c1df282010-02-26 09:51:20 +000063
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000064static const struct par_master par_master_internal = {
Nico Huber239dc802026-06-24 23:04:58 +020065 .chip_readb = mmio_chip_readb,
66 .chip_readw = mmio_chip_readw,
67 .chip_readl = mmio_chip_readl,
68 .chip_readn = mmio_chip_readn,
69 .chip_writeb = mmio_chip_writeb,
70 .chip_writew = mmio_chip_writew,
71 .chip_writel = mmio_chip_writel,
Thomas Heijligen43040f22022-06-23 14:38:35 +020072 .chip_writen = fallback_chip_writen,
Nico Huber0e76d992023-01-12 20:22:55 +010073 .map_flash = physmap,
74 .unmap_flash = physunmap,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +000075};
76
77enum chipbustype internal_buses_supported = BUS_NONE;
78
Felix Singerb8db74a2022-08-19 00:19:26 +020079static int get_params(bool *boardenable, bool *boardmismatch,
80 bool *force_laptop, bool *not_a_laptop,
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +110081 char **board_vendor, char **board_model)
Uwe Hermanna0869322009-05-14 20:41:57 +000082{
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000083 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +000084
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +110085 /* default values. */
Felix Singerb8db74a2022-08-19 00:19:26 +020086 *force_laptop = false;
87 *not_a_laptop = false;
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +110088 *board_vendor = NULL;
89 *board_model = NULL;
90
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +000091 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000092 if (arg && !strcmp(arg,"force")) {
Felix Singerb8db74a2022-08-19 00:19:26 +020093 *boardenable = true;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000094 } else if (arg && !strlen(arg)) {
95 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +000096 free(arg);
97 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000098 } else if (arg) {
99 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000100 free(arg);
101 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000102 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000103 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000104
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000105 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000106 if (arg && !strcmp(arg,"force")) {
Felix Singerb8db74a2022-08-19 00:19:26 +0200107 *boardmismatch = true;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000108 } else if (arg && !strlen(arg)) {
109 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000110 free(arg);
111 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000112 } else if (arg) {
113 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000114 free(arg);
115 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000116 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000117 free(arg);
118
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000119 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000120 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Felix Singerb8db74a2022-08-19 00:19:26 +0200121 *force_laptop = true;
Stefan Taunera28087f2011-09-13 23:14:25 +0000122 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
Felix Singerb8db74a2022-08-19 00:19:26 +0200123 *not_a_laptop = true;
Stefan Taunera28087f2011-09-13 23:14:25 +0000124 else if (arg && !strlen(arg)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000125 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000126 free(arg);
127 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000128 } else if (arg) {
129 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000130 free(arg);
131 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000132 }
133 free(arg);
134
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000135 arg = extract_programmer_param("mainboard");
136 if (arg && strlen(arg)) {
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100137 if (board_parse_parameter(arg, board_vendor, board_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000138 free(arg);
139 return 1;
140 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000141 } else if (arg && !strlen(arg)) {
142 msg_perr("Missing argument for mainboard.\n");
143 free(arg);
144 return 1;
145 }
146 free(arg);
147
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100148 return 0;
149}
150
Nico Hubere3a26882023-01-11 21:45:51 +0100151static int internal_init(struct flashprog_programmer *const prog)
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100152{
153 int ret = 0;
Felix Singerb8db74a2022-08-19 00:19:26 +0200154 bool force_laptop;
155 bool not_a_laptop;
Edward O'Callaghand91ee2c2022-02-03 11:55:13 +1100156 char *board_vendor;
157 char *board_model;
158#if defined(__i386__) || defined(__x86_64__)
159 const char *cb_vendor = NULL;
160 const char *cb_model = NULL;
161#endif
162
163 ret = get_params(&force_boardenable, &force_boardmismatch,
164 &force_laptop, &not_a_laptop,
165 &board_vendor, &board_model);
166 if (ret)
167 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000168
Nico Huber89569d62023-01-12 23:31:40 +0100169 struct internal_data *const internal = malloc(sizeof(*internal));
170 if (!internal) {
171 msg_perr("Out of memory!\n");
172 ret = 1;
173 goto internal_init_exit;
174 }
175 if (register_shutdown(shutdown_free, internal)) {
176 ret = 1;
177 goto internal_init_exit;
178 }
Nico Huber47aa85c2026-02-21 14:57:20 +0100179 internal->rom_base = 0; /* Default to top aligned flash at 4 GB. */
Nico Huber89569d62023-01-12 23:31:40 +0100180 internal->max_rom_decode = 0;
181 prog->data = internal;
182
Edward O'Callaghanbd275812022-11-28 11:20:44 +1100183 /* Unconditionally reset global state from previous operation. */
184 laptop_ok = false;
185
Michael Karcherb9dbe482011-05-11 17:07:07 +0000186 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000187 * is found, the host controller init routine sets the
188 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000189 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000190 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000191
Nico Hubere3a26882023-01-11 21:45:51 +0100192 if (try_mtd(prog) == 0) {
Jacob Garber1c091d12019-08-12 11:14:14 -0600193 ret = 0;
194 goto internal_init_exit;
195 }
David Hendricksf9a30552015-05-23 20:30:30 -0700196
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000197 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600198 if (pci_init_common() != 0) {
199 ret = 1;
200 goto internal_init_exit;
201 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000202
Nico Huber47aa85c2026-02-21 14:57:20 +0100203 if (processor_flash_enable(prog)) {
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000204 msg_perr("Processor detection/init failed.\n"
205 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600206 ret = 1;
207 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000208 }
209
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200210#if defined(__i386__) || defined(__x86_64__)
Peter Marheinedf3672d2022-01-19 17:11:09 +1100211 if (rget_io_perms()) {
212 ret = 1;
213 goto internal_init_exit;
214 }
215
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000216 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
217 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000218 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000219 " match the current coreboot IDs of the mainboard (%s:%s).\n",
220 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600221 if (!force_boardmismatch) {
222 ret = 1;
223 goto internal_init_exit;
224 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000225 msg_pinfo("Continuing anyway.\n");
226 }
227 }
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000228
Nico Huber2e50cdc2018-09-23 20:20:26 +0200229 is_laptop = 2; /* Assume that we don't know by default. */
230
Michael Karcher6701ee82010-01-20 14:14:11 +0000231 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000232
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000233 /* In case Super I/O probing would cause pretty explosions. */
Nico Huber7c717c32023-01-12 00:28:15 +0100234 board_handle_before_superio(prog);
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000235
Uwe Hermann43959702010-03-13 17:28:29 +0000236 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000237 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000238#else
239 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
240 * by coreboot.
241 * FIXME: Find a replacement for DMI on non-x86.
242 * FIXME: Enable Super I/O probing once port I/O is possible.
243 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000244#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000245
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000246 /* Check laptop whitelist. */
Nico Huber7c717c32023-01-12 00:28:15 +0100247 board_handle_before_laptop(prog);
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000248
Nico Huber2e50cdc2018-09-23 20:20:26 +0200249 /*
250 * Disable all internal buses by default if we are not sure
251 * this isn't a laptop. Board-enables may override this,
252 * non-legacy buses (SPI and opaque atm) are probed anyway.
253 */
254 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
255 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000256
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000257 /* try to enable it. Failure IS an option, since not all motherboards
258 * really need this to be done, etc., etc.
259 */
Nico Huber929d2e12023-01-12 00:47:05 +0100260 ret = chipset_flash_enable(prog);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000261 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000262 msg_perr("WARNING: No chipset found. Flash detection "
263 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600264 } else if (ret == ERROR_FATAL) {
265 goto internal_init_exit;
266 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000267
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200268#if defined(__i386__) || defined(__x86_64__)
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000269 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
270 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Nico Huber89569d62023-01-12 23:31:40 +0100271 init_superio_ite(prog);
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000272
Nico Huber7c717c32023-01-12 00:28:15 +0100273 if (board_flash_enable(prog, board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000274 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600275 ret = 1;
276 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000277 }
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000278#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000279
Nico Huber89569d62023-01-12 23:31:40 +0100280 if (internal_buses_supported & BUS_NONSPI) {
281 register_par_master(&par_master_internal, internal_buses_supported,
Nico Huber47aa85c2026-02-21 14:57:20 +0100282 internal->rom_base, internal->max_rom_decode, NULL);
Nico Huber89569d62023-01-12 23:31:40 +0100283 }
Nico Huber2e50cdc2018-09-23 20:20:26 +0200284
285 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
286 if (is_laptop && !laptop_ok) {
287 msg_pinfo("========================================================================\n");
288 if (is_laptop == 1) {
Nico Huberc3b02dc2023-08-12 01:13:45 +0200289 msg_pinfo("You seem to be running flashprog on an unknown laptop. Some\n"
Nico Huber2e50cdc2018-09-23 20:20:26 +0200290 "internal buses have been disabled for safety reasons.\n\n");
291 } else {
Nico Huberc3b02dc2023-08-12 01:13:45 +0200292 msg_pinfo("You may be running flashprog on an unknown laptop. We could not\n"
Nico Huber2e50cdc2018-09-23 20:20:26 +0200293 "detect this for sure because your vendor has not set up the SMBIOS\n"
294 "tables correctly. Some internal buses have been disabled for\n"
295 "safety reasons. You can enforce using all buses by adding\n"
296 " -p internal:laptop=this_is_not_a_laptop\n"
297 "to the command line, but please read the following warning if you\n"
298 "are not sure.\n\n");
299 }
300 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
301 "recommend to use the vendor flashing utility. The embedded controller\n"
302 "(EC) in these machines often interacts badly with flashing.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200303 "See the manpage and https://flashprog.org/Laptops for details.\n\n"
Nico Huber2e50cdc2018-09-23 20:20:26 +0200304 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
305 "and write may brick your laptop.\n"
306 "Read and probe may irritate your EC and cause fan failure, backlight\n"
307 "failure and sudden poweroff.\n"
308 "You have been warned.\n"
309 "========================================================================\n");
310 }
311
Jacob Garber1c091d12019-08-12 11:14:14 -0600312 ret = 0;
313
314internal_init_exit:
315 free(board_vendor);
316 free(board_model);
317
318 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000319}
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000320
Thomas Heijligencc853d82021-05-04 15:32:17 +0200321const struct programmer_entry programmer_internal = {
322 .name = "internal",
323 .type = OTHER,
324 .devs.note = NULL,
325 .init = internal_init,
Thomas Heijligencc853d82021-05-04 15:32:17 +0200326};