1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2009 Carl-Daniel Hailfinger
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
9*0d6140beSAndroid Build Coastguard Worker * (at your option) any later version.
10*0d6140beSAndroid Build Coastguard Worker *
11*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
15*0d6140beSAndroid Build Coastguard Worker */
16*0d6140beSAndroid Build Coastguard Worker
17*0d6140beSAndroid Build Coastguard Worker #include <strings.h>
18*0d6140beSAndroid Build Coastguard Worker #include <string.h>
19*0d6140beSAndroid Build Coastguard Worker #include <stdbool.h>
20*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
21*0d6140beSAndroid Build Coastguard Worker
22*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
23*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
24*0d6140beSAndroid Build Coastguard Worker #include "platform/pci.h"
25*0d6140beSAndroid Build Coastguard Worker
26*0d6140beSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
27*0d6140beSAndroid Build Coastguard Worker #include "hwaccess_x86_io.h"
28*0d6140beSAndroid Build Coastguard Worker #endif
29*0d6140beSAndroid Build Coastguard Worker
30*0d6140beSAndroid Build Coastguard Worker bool force_boardmismatch = false;
31*0d6140beSAndroid Build Coastguard Worker
32*0d6140beSAndroid Build Coastguard Worker enum chipbustype internal_buses_supported = BUS_NONE;
33*0d6140beSAndroid Build Coastguard Worker
34*0d6140beSAndroid Build Coastguard Worker
get_params(const struct programmer_cfg * cfg,bool * boardenable,bool * boardmismatch,bool * force_laptop,bool * not_a_laptop,char ** board_vendor,char ** board_model)35*0d6140beSAndroid Build Coastguard Worker static int get_params(const struct programmer_cfg *cfg,
36*0d6140beSAndroid Build Coastguard Worker bool *boardenable, bool *boardmismatch,
37*0d6140beSAndroid Build Coastguard Worker bool *force_laptop, bool *not_a_laptop,
38*0d6140beSAndroid Build Coastguard Worker char **board_vendor, char **board_model)
39*0d6140beSAndroid Build Coastguard Worker {
40*0d6140beSAndroid Build Coastguard Worker char *arg;
41*0d6140beSAndroid Build Coastguard Worker
42*0d6140beSAndroid Build Coastguard Worker /* default values. */
43*0d6140beSAndroid Build Coastguard Worker *force_laptop = false;
44*0d6140beSAndroid Build Coastguard Worker *not_a_laptop = false;
45*0d6140beSAndroid Build Coastguard Worker *board_vendor = NULL;
46*0d6140beSAndroid Build Coastguard Worker *board_model = NULL;
47*0d6140beSAndroid Build Coastguard Worker
48*0d6140beSAndroid Build Coastguard Worker arg = extract_programmer_param_str(cfg, "boardenable");
49*0d6140beSAndroid Build Coastguard Worker if (arg && !strcmp(arg,"force")) {
50*0d6140beSAndroid Build Coastguard Worker *boardenable = true;
51*0d6140beSAndroid Build Coastguard Worker } else if (arg && !strlen(arg)) {
52*0d6140beSAndroid Build Coastguard Worker msg_perr("Missing argument for boardenable.\n");
53*0d6140beSAndroid Build Coastguard Worker free(arg);
54*0d6140beSAndroid Build Coastguard Worker return 1;
55*0d6140beSAndroid Build Coastguard Worker } else if (arg) {
56*0d6140beSAndroid Build Coastguard Worker msg_perr("Unknown argument for boardenable: %s\n", arg);
57*0d6140beSAndroid Build Coastguard Worker free(arg);
58*0d6140beSAndroid Build Coastguard Worker return 1;
59*0d6140beSAndroid Build Coastguard Worker }
60*0d6140beSAndroid Build Coastguard Worker free(arg);
61*0d6140beSAndroid Build Coastguard Worker
62*0d6140beSAndroid Build Coastguard Worker arg = extract_programmer_param_str(cfg, "boardmismatch");
63*0d6140beSAndroid Build Coastguard Worker if (arg && !strcmp(arg,"force")) {
64*0d6140beSAndroid Build Coastguard Worker *boardmismatch = true;
65*0d6140beSAndroid Build Coastguard Worker } else if (arg && !strlen(arg)) {
66*0d6140beSAndroid Build Coastguard Worker msg_perr("Missing argument for boardmismatch.\n");
67*0d6140beSAndroid Build Coastguard Worker free(arg);
68*0d6140beSAndroid Build Coastguard Worker return 1;
69*0d6140beSAndroid Build Coastguard Worker } else if (arg) {
70*0d6140beSAndroid Build Coastguard Worker msg_perr("Unknown argument for boardmismatch: %s\n", arg);
71*0d6140beSAndroid Build Coastguard Worker free(arg);
72*0d6140beSAndroid Build Coastguard Worker return 1;
73*0d6140beSAndroid Build Coastguard Worker }
74*0d6140beSAndroid Build Coastguard Worker free(arg);
75*0d6140beSAndroid Build Coastguard Worker
76*0d6140beSAndroid Build Coastguard Worker arg = extract_programmer_param_str(cfg, "laptop");
77*0d6140beSAndroid Build Coastguard Worker if (arg && !strcmp(arg, "force_I_want_a_brick"))
78*0d6140beSAndroid Build Coastguard Worker *force_laptop = true;
79*0d6140beSAndroid Build Coastguard Worker else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
80*0d6140beSAndroid Build Coastguard Worker *not_a_laptop = true;
81*0d6140beSAndroid Build Coastguard Worker else if (arg && !strlen(arg)) {
82*0d6140beSAndroid Build Coastguard Worker msg_perr("Missing argument for laptop.\n");
83*0d6140beSAndroid Build Coastguard Worker free(arg);
84*0d6140beSAndroid Build Coastguard Worker return 1;
85*0d6140beSAndroid Build Coastguard Worker } else if (arg) {
86*0d6140beSAndroid Build Coastguard Worker msg_perr("Unknown argument for laptop: %s\n", arg);
87*0d6140beSAndroid Build Coastguard Worker free(arg);
88*0d6140beSAndroid Build Coastguard Worker return 1;
89*0d6140beSAndroid Build Coastguard Worker }
90*0d6140beSAndroid Build Coastguard Worker free(arg);
91*0d6140beSAndroid Build Coastguard Worker
92*0d6140beSAndroid Build Coastguard Worker arg = extract_programmer_param_str(cfg, "mainboard");
93*0d6140beSAndroid Build Coastguard Worker if (arg && strlen(arg)) {
94*0d6140beSAndroid Build Coastguard Worker if (board_parse_parameter(arg, board_vendor, board_model)) {
95*0d6140beSAndroid Build Coastguard Worker free(arg);
96*0d6140beSAndroid Build Coastguard Worker return 1;
97*0d6140beSAndroid Build Coastguard Worker }
98*0d6140beSAndroid Build Coastguard Worker } else if (arg && !strlen(arg)) {
99*0d6140beSAndroid Build Coastguard Worker msg_perr("Missing argument for mainboard.\n");
100*0d6140beSAndroid Build Coastguard Worker free(arg);
101*0d6140beSAndroid Build Coastguard Worker return 1;
102*0d6140beSAndroid Build Coastguard Worker }
103*0d6140beSAndroid Build Coastguard Worker free(arg);
104*0d6140beSAndroid Build Coastguard Worker
105*0d6140beSAndroid Build Coastguard Worker return 0;
106*0d6140beSAndroid Build Coastguard Worker }
107*0d6140beSAndroid Build Coastguard Worker
report_nonwl_laptop_detected(const struct board_cfg * bcfg)108*0d6140beSAndroid Build Coastguard Worker static void report_nonwl_laptop_detected(const struct board_cfg *bcfg)
109*0d6140beSAndroid Build Coastguard Worker {
110*0d6140beSAndroid Build Coastguard Worker const int is_laptop = bcfg->is_laptop;
111*0d6140beSAndroid Build Coastguard Worker const bool laptop_ok = bcfg->laptop_ok;
112*0d6140beSAndroid Build Coastguard Worker
113*0d6140beSAndroid Build Coastguard Worker if (!is_laptop || laptop_ok)
114*0d6140beSAndroid Build Coastguard Worker return;
115*0d6140beSAndroid Build Coastguard Worker
116*0d6140beSAndroid Build Coastguard Worker msg_pinfo("========================================================================\n");
117*0d6140beSAndroid Build Coastguard Worker if (is_laptop == 1) {
118*0d6140beSAndroid Build Coastguard Worker msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
119*0d6140beSAndroid Build Coastguard Worker "internal buses have been disabled for safety reasons.\n\n");
120*0d6140beSAndroid Build Coastguard Worker } else {
121*0d6140beSAndroid Build Coastguard Worker msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
122*0d6140beSAndroid Build Coastguard Worker "detect this for sure because your vendor has not set up the SMBIOS\n"
123*0d6140beSAndroid Build Coastguard Worker "tables correctly. Some internal buses have been disabled for\n"
124*0d6140beSAndroid Build Coastguard Worker "safety reasons. You can enforce using all buses by adding\n"
125*0d6140beSAndroid Build Coastguard Worker " -p internal:laptop=this_is_not_a_laptop\n"
126*0d6140beSAndroid Build Coastguard Worker "to the command line, but please read the following warning if you\n"
127*0d6140beSAndroid Build Coastguard Worker "are not sure.\n\n");
128*0d6140beSAndroid Build Coastguard Worker }
129*0d6140beSAndroid Build Coastguard Worker msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
130*0d6140beSAndroid Build Coastguard Worker "recommend to use the vendor flashing utility. The embedded controller\n"
131*0d6140beSAndroid Build Coastguard Worker "(EC) in these machines often interacts badly with flashing.\n"
132*0d6140beSAndroid Build Coastguard Worker "See the manpage and https://flashrom.org/Laptops for details.\n\n"
133*0d6140beSAndroid Build Coastguard Worker "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
134*0d6140beSAndroid Build Coastguard Worker "and write may brick your laptop.\n"
135*0d6140beSAndroid Build Coastguard Worker "Read and probe may irritate your EC and cause fan failure, backlight\n"
136*0d6140beSAndroid Build Coastguard Worker "failure and sudden poweroff.\n"
137*0d6140beSAndroid Build Coastguard Worker "You have been warned.\n"
138*0d6140beSAndroid Build Coastguard Worker "========================================================================\n");
139*0d6140beSAndroid Build Coastguard Worker }
140*0d6140beSAndroid Build Coastguard Worker
internal_init(const struct programmer_cfg * cfg)141*0d6140beSAndroid Build Coastguard Worker int internal_init(const struct programmer_cfg *cfg)
142*0d6140beSAndroid Build Coastguard Worker {
143*0d6140beSAndroid Build Coastguard Worker int ret = 0;
144*0d6140beSAndroid Build Coastguard Worker bool force_laptop;
145*0d6140beSAndroid Build Coastguard Worker bool not_a_laptop;
146*0d6140beSAndroid Build Coastguard Worker char *board_vendor;
147*0d6140beSAndroid Build Coastguard Worker char *board_model;
148*0d6140beSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
149*0d6140beSAndroid Build Coastguard Worker const char *cb_vendor = NULL;
150*0d6140beSAndroid Build Coastguard Worker const char *cb_model = NULL;
151*0d6140beSAndroid Build Coastguard Worker #endif
152*0d6140beSAndroid Build Coastguard Worker bool force_boardenable = false;
153*0d6140beSAndroid Build Coastguard Worker struct board_cfg bcfg = {0};
154*0d6140beSAndroid Build Coastguard Worker
155*0d6140beSAndroid Build Coastguard Worker ret = get_params(cfg,
156*0d6140beSAndroid Build Coastguard Worker &force_boardenable, &force_boardmismatch,
157*0d6140beSAndroid Build Coastguard Worker &force_laptop, ¬_a_laptop,
158*0d6140beSAndroid Build Coastguard Worker &board_vendor, &board_model);
159*0d6140beSAndroid Build Coastguard Worker if (ret)
160*0d6140beSAndroid Build Coastguard Worker return ret;
161*0d6140beSAndroid Build Coastguard Worker
162*0d6140beSAndroid Build Coastguard Worker /* Default to Parallel/LPC/FWH flash devices. If a known host controller
163*0d6140beSAndroid Build Coastguard Worker * is found, the host controller init routine sets the
164*0d6140beSAndroid Build Coastguard Worker * internal_buses_supported bitfield.
165*0d6140beSAndroid Build Coastguard Worker */
166*0d6140beSAndroid Build Coastguard Worker internal_buses_supported = BUS_NONSPI;
167*0d6140beSAndroid Build Coastguard Worker
168*0d6140beSAndroid Build Coastguard Worker if (try_mtd(cfg) == 0) {
169*0d6140beSAndroid Build Coastguard Worker ret = 0;
170*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
171*0d6140beSAndroid Build Coastguard Worker }
172*0d6140beSAndroid Build Coastguard Worker
173*0d6140beSAndroid Build Coastguard Worker #if (defined (__i386__) || defined (__x86_64__) || defined(__amd64__))
174*0d6140beSAndroid Build Coastguard Worker /* Initialize PCI access for flash enables */
175*0d6140beSAndroid Build Coastguard Worker if (pci_init_common() != 0) {
176*0d6140beSAndroid Build Coastguard Worker ret = 1;
177*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
178*0d6140beSAndroid Build Coastguard Worker }
179*0d6140beSAndroid Build Coastguard Worker #endif // if IS_X86
180*0d6140beSAndroid Build Coastguard Worker
181*0d6140beSAndroid Build Coastguard Worker if (processor_flash_enable()) {
182*0d6140beSAndroid Build Coastguard Worker msg_perr("Processor detection/init failed.\n"
183*0d6140beSAndroid Build Coastguard Worker "Aborting.\n");
184*0d6140beSAndroid Build Coastguard Worker ret = 1;
185*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
186*0d6140beSAndroid Build Coastguard Worker }
187*0d6140beSAndroid Build Coastguard Worker
188*0d6140beSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
189*0d6140beSAndroid Build Coastguard Worker if (rget_io_perms()) {
190*0d6140beSAndroid Build Coastguard Worker ret = 1;
191*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
192*0d6140beSAndroid Build Coastguard Worker }
193*0d6140beSAndroid Build Coastguard Worker
194*0d6140beSAndroid Build Coastguard Worker if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
195*0d6140beSAndroid Build Coastguard Worker if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
196*0d6140beSAndroid Build Coastguard Worker msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
197*0d6140beSAndroid Build Coastguard Worker " match the current coreboot IDs of the mainboard (%s:%s).\n",
198*0d6140beSAndroid Build Coastguard Worker board_vendor, board_model, cb_vendor, cb_model);
199*0d6140beSAndroid Build Coastguard Worker if (!force_boardmismatch) {
200*0d6140beSAndroid Build Coastguard Worker ret = 1;
201*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
202*0d6140beSAndroid Build Coastguard Worker }
203*0d6140beSAndroid Build Coastguard Worker msg_pinfo("Continuing anyway.\n");
204*0d6140beSAndroid Build Coastguard Worker }
205*0d6140beSAndroid Build Coastguard Worker }
206*0d6140beSAndroid Build Coastguard Worker
207*0d6140beSAndroid Build Coastguard Worker bcfg.is_laptop = 2; /* Assume that we don't know by default. */
208*0d6140beSAndroid Build Coastguard Worker
209*0d6140beSAndroid Build Coastguard Worker dmi_init(&bcfg.is_laptop);
210*0d6140beSAndroid Build Coastguard Worker
211*0d6140beSAndroid Build Coastguard Worker /* In case Super I/O probing would cause pretty explosions. */
212*0d6140beSAndroid Build Coastguard Worker board_handle_before_superio(&bcfg, force_boardenable);
213*0d6140beSAndroid Build Coastguard Worker
214*0d6140beSAndroid Build Coastguard Worker /* Probe for the Super I/O chip and fill global struct superio. */
215*0d6140beSAndroid Build Coastguard Worker probe_superio();
216*0d6140beSAndroid Build Coastguard Worker #else
217*0d6140beSAndroid Build Coastguard Worker /* FIXME: Enable cbtable searching on all non-x86 platforms supported
218*0d6140beSAndroid Build Coastguard Worker * by coreboot.
219*0d6140beSAndroid Build Coastguard Worker * FIXME: Find a replacement for DMI on non-x86.
220*0d6140beSAndroid Build Coastguard Worker * FIXME: Enable Super I/O probing once port I/O is possible.
221*0d6140beSAndroid Build Coastguard Worker */
222*0d6140beSAndroid Build Coastguard Worker #endif
223*0d6140beSAndroid Build Coastguard Worker
224*0d6140beSAndroid Build Coastguard Worker /* Check laptop whitelist. */
225*0d6140beSAndroid Build Coastguard Worker board_handle_before_laptop(&bcfg, force_boardenable);
226*0d6140beSAndroid Build Coastguard Worker
227*0d6140beSAndroid Build Coastguard Worker /*
228*0d6140beSAndroid Build Coastguard Worker * Disable all internal buses by default if we are not sure
229*0d6140beSAndroid Build Coastguard Worker * this isn't a laptop. Board-enables may override this,
230*0d6140beSAndroid Build Coastguard Worker * non-legacy buses (SPI and opaque atm) are probed anyway.
231*0d6140beSAndroid Build Coastguard Worker */
232*0d6140beSAndroid Build Coastguard Worker if (bcfg.is_laptop && !(bcfg.laptop_ok || force_laptop || (not_a_laptop && bcfg.is_laptop == 2)))
233*0d6140beSAndroid Build Coastguard Worker internal_buses_supported = BUS_NONE;
234*0d6140beSAndroid Build Coastguard Worker
235*0d6140beSAndroid Build Coastguard Worker /* try to enable it. Failure IS an option, since not all motherboards
236*0d6140beSAndroid Build Coastguard Worker * really need this to be done, etc., etc.
237*0d6140beSAndroid Build Coastguard Worker */
238*0d6140beSAndroid Build Coastguard Worker struct programmer_cfg icfg = *cfg;
239*0d6140beSAndroid Build Coastguard Worker icfg.bcfg = &bcfg;
240*0d6140beSAndroid Build Coastguard Worker ret = chipset_flash_enable(&icfg);
241*0d6140beSAndroid Build Coastguard Worker if (ret == -2) {
242*0d6140beSAndroid Build Coastguard Worker msg_perr("WARNING: No chipset found. Flash detection "
243*0d6140beSAndroid Build Coastguard Worker "will most likely fail.\n");
244*0d6140beSAndroid Build Coastguard Worker } else if (ret == ERROR_FLASHROM_FATAL) {
245*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
246*0d6140beSAndroid Build Coastguard Worker }
247*0d6140beSAndroid Build Coastguard Worker
248*0d6140beSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
249*0d6140beSAndroid Build Coastguard Worker /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
250*0d6140beSAndroid Build Coastguard Worker * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
251*0d6140beSAndroid Build Coastguard Worker init_superio_ite(cfg);
252*0d6140beSAndroid Build Coastguard Worker
253*0d6140beSAndroid Build Coastguard Worker if (board_flash_enable(&bcfg,
254*0d6140beSAndroid Build Coastguard Worker board_vendor, board_model, cb_vendor, cb_model, force_boardenable)) {
255*0d6140beSAndroid Build Coastguard Worker msg_perr("Aborting to be safe.\n");
256*0d6140beSAndroid Build Coastguard Worker ret = 1;
257*0d6140beSAndroid Build Coastguard Worker goto internal_init_exit;
258*0d6140beSAndroid Build Coastguard Worker }
259*0d6140beSAndroid Build Coastguard Worker #endif
260*0d6140beSAndroid Build Coastguard Worker
261*0d6140beSAndroid Build Coastguard Worker internal_par_init(internal_buses_supported);
262*0d6140beSAndroid Build Coastguard Worker
263*0d6140beSAndroid Build Coastguard Worker /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
264*0d6140beSAndroid Build Coastguard Worker report_nonwl_laptop_detected(&bcfg);
265*0d6140beSAndroid Build Coastguard Worker
266*0d6140beSAndroid Build Coastguard Worker ret = 0;
267*0d6140beSAndroid Build Coastguard Worker
268*0d6140beSAndroid Build Coastguard Worker internal_init_exit:
269*0d6140beSAndroid Build Coastguard Worker free(board_vendor);
270*0d6140beSAndroid Build Coastguard Worker free(board_model);
271*0d6140beSAndroid Build Coastguard Worker
272*0d6140beSAndroid Build Coastguard Worker return ret;
273*0d6140beSAndroid Build Coastguard Worker }
274*0d6140beSAndroid Build Coastguard Worker
275*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry programmer_internal = {
276*0d6140beSAndroid Build Coastguard Worker .name = "internal",
277*0d6140beSAndroid Build Coastguard Worker .type = OTHER,
278*0d6140beSAndroid Build Coastguard Worker .devs.note = NULL,
279*0d6140beSAndroid Build Coastguard Worker .init = internal_init,
280*0d6140beSAndroid Build Coastguard Worker };
281