flashrom 

flashrom Svn Source Tree

Root/trunk/internal.c

1/*
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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <strings.h>
22#include <string.h>
23#include <stdlib.h>
24#include "flash.h"
25#include "programmer.h"
26#include "hwaccess.h"
27
28#if NEED_PCI == 1
29struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
30{
31struct pci_dev *temp;
32
33for (temp = pacc->devices; temp; temp = temp->next)
34if (pci_filter_match(&filter, temp))
35return temp;
36
37return NULL;
38}
39
40struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
41{
42struct pci_dev *temp;
43struct pci_filter filter;
44uint16_t tmp2;
45
46pci_filter_init(NULL, &filter);
47filter.vendor = vendor;
48
49for (temp = pacc->devices; temp; temp = temp->next)
50if (pci_filter_match(&filter, temp)) {
51/* Read PCI class */
52tmp2 = pci_read_word(temp, 0x0a);
53if (tmp2 == devclass)
54return temp;
55}
56
57return NULL;
58}
59
60struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
61{
62struct pci_dev *temp;
63struct pci_filter filter;
64
65pci_filter_init(NULL, &filter);
66filter.vendor = vendor;
67filter.device = device;
68
69for (temp = pacc->devices; temp; temp = temp->next)
70if (pci_filter_match(&filter, temp))
71return temp;
72
73return NULL;
74}
75
76struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
77 uint16_t card_vendor, uint16_t card_device)
78{
79struct pci_dev *temp;
80struct pci_filter filter;
81
82pci_filter_init(NULL, &filter);
83filter.vendor = vendor;
84filter.device = device;
85
86for (temp = pacc->devices; temp; temp = temp->next)
87if (pci_filter_match(&filter, temp)) {
88if ((card_vendor ==
89 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
90 && (card_device ==
91pci_read_word(temp, PCI_SUBSYSTEM_ID)))
92return temp;
93}
94
95return NULL;
96}
97#endif
98
99#if CONFIG_INTERNAL == 1
100int force_boardenable = 0;
101int force_boardmismatch = 0;
102
103#if defined(__i386__) || defined(__x86_64__)
104void probe_superio(void)
105{
106probe_superio_winbond();
107/* ITE probe causes SMSC LPC47N217 to power off the serial UART.
108 * Always probe for SMSC first, and if a SMSC Super I/O is detected
109 * at a given I/O port, do _not_ probe that port with the ITE probe.
110 * This means SMSC probing must be done before ITE probing.
111 */
112//probe_superio_smsc();
113probe_superio_ite();
114}
115
116int superio_count = 0;
117#define SUPERIO_MAX_COUNT 3
118
119struct superio superios[SUPERIO_MAX_COUNT];
120
121int register_superio(struct superio s)
122{
123if (superio_count == SUPERIO_MAX_COUNT)
124return 1;
125superios[superio_count++] = s;
126return 0;
127}
128
129#endif
130
131int is_laptop = 0;
132int laptop_ok = 0;
133
134static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
135 chipaddr addr);
136static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
137 chipaddr addr);
138static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
139 chipaddr addr);
140static uint8_t internal_chip_readb(const struct flashctx *flash,
141 const chipaddr addr);
142static uint16_t internal_chip_readw(const struct flashctx *flash,
143 const chipaddr addr);
144static uint32_t internal_chip_readl(const struct flashctx *flash,
145 const chipaddr addr);
146static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
147const chipaddr addr, size_t len);
148static const struct par_master par_master_internal = {
149.chip_readb= internal_chip_readb,
150.chip_readw= internal_chip_readw,
151.chip_readl= internal_chip_readl,
152.chip_readn= internal_chip_readn,
153.chip_writeb= internal_chip_writeb,
154.chip_writew= internal_chip_writew,
155.chip_writel= internal_chip_writel,
156.chip_writen= fallback_chip_writen,
157};
158
159enum chipbustype internal_buses_supported = BUS_NONE;
160
161int internal_init(void)
162{
163#if defined __FLASHROM_LITTLE_ENDIAN__
164int ret = 0;
165#endif
166int force_laptop = 0;
167int not_a_laptop = 0;
168const char *board_vendor = NULL;
169const char *board_model = NULL;
170#if IS_X86 || IS_ARM
171const char *cb_vendor = NULL;
172const char *cb_model = NULL;
173#endif
174char *arg;
175
176arg = extract_programmer_param("boardenable");
177if (arg && !strcmp(arg,"force")) {
178force_boardenable = 1;
179} else if (arg && !strlen(arg)) {
180msg_perr("Missing argument for boardenable.\n");
181free(arg);
182return 1;
183} else if (arg) {
184msg_perr("Unknown argument for boardenable: %s\n", arg);
185free(arg);
186return 1;
187}
188free(arg);
189
190arg = extract_programmer_param("boardmismatch");
191if (arg && !strcmp(arg,"force")) {
192force_boardmismatch = 1;
193} else if (arg && !strlen(arg)) {
194msg_perr("Missing argument for boardmismatch.\n");
195free(arg);
196return 1;
197} else if (arg) {
198msg_perr("Unknown argument for boardmismatch: %s\n", arg);
199free(arg);
200return 1;
201}
202free(arg);
203
204arg = extract_programmer_param("laptop");
205if (arg && !strcmp(arg, "force_I_want_a_brick"))
206force_laptop = 1;
207else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
208not_a_laptop = 1;
209else if (arg && !strlen(arg)) {
210msg_perr("Missing argument for laptop.\n");
211free(arg);
212return 1;
213} else if (arg) {
214msg_perr("Unknown argument for laptop: %s\n", arg);
215free(arg);
216return 1;
217}
218free(arg);
219
220arg = extract_programmer_param("mainboard");
221if (arg && strlen(arg)) {
222if (board_parse_parameter(arg, &board_vendor, &board_model)) {
223free(arg);
224return 1;
225}
226} else if (arg && !strlen(arg)) {
227msg_perr("Missing argument for mainboard.\n");
228free(arg);
229return 1;
230}
231free(arg);
232
233if (rget_io_perms())
234return 1;
235
236/* Default to Parallel/LPC/FWH flash devices. If a known host controller
237 * is found, the host controller init routine sets the
238 * internal_buses_supported bitfield.
239 */
240internal_buses_supported = BUS_NONSPI;
241
242/* Initialize PCI access for flash enables */
243if (pci_init_common() != 0)
244return 1;
245
246if (processor_flash_enable()) {
247msg_perr("Processor detection/init failed.\n"
248 "Aborting.\n");
249return 1;
250}
251
252#if IS_X86 || IS_ARM
253if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
254if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
255msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
256 " match the current coreboot IDs of the mainboard (%s:%s).\n",
257 board_vendor, board_model, cb_vendor, cb_model);
258if (!force_boardmismatch)
259return 1;
260msg_pinfo("Continuing anyway.\n");
261}
262}
263#endif
264
265#if IS_X86
266dmi_init();
267
268/* In case Super I/O probing would cause pretty explosions. */
269board_handle_before_superio();
270
271/* Probe for the Super I/O chip and fill global struct superio. */
272probe_superio();
273#else
274/* FIXME: Enable cbtable searching on all non-x86 platforms supported
275 * by coreboot.
276 * FIXME: Find a replacement for DMI on non-x86.
277 * FIXME: Enable Super I/O probing once port I/O is possible.
278 */
279#endif
280
281/* Check laptop whitelist. */
282board_handle_before_laptop();
283
284/* Warn if a non-whitelisted laptop is detected. */
285if (is_laptop && !laptop_ok) {
286msg_perr("========================================================================\n");
287if (is_laptop == 1) {
288msg_perr("WARNING! You seem to be running flashrom on an unsupported laptop.\n");
289} else {
290msg_perr("WARNING! You may be running flashrom on an unsupported laptop. We could\n"
291 "not detect this for sure because your vendor has not setup the SMBIOS\n"
292 "tables correctly. You can enforce execution by adding\n"
293 "'-p internal:laptop=this_is_not_a_laptop' to the command line, but\n"
294 "please read the following warning if you are not sure.\n\n");
295}
296msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
297 "recommend to use the vendor flashing utility. The embedded controller\n"
298 "(EC) in these machines often interacts badly with flashing.\n"
299 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
300 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
301 "and write may brick your laptop.\n"
302 "Read and probe may irritate your EC and cause fan failure, backlight\n"
303 "failure and sudden poweroff.\n"
304 "You have been warned.\n"
305 "========================================================================\n");
306
307if (force_laptop || (not_a_laptop && (is_laptop == 2))) {
308msg_perr("Proceeding anyway because user forced us to.\n");
309} else {
310msg_perr("Aborting.\n");
311return 1;
312}
313}
314
315#ifdef __FLASHROM_LITTLE_ENDIAN__
316/* try to enable it. Failure IS an option, since not all motherboards
317 * really need this to be done, etc., etc.
318 */
319ret = chipset_flash_enable();
320if (ret == -2) {
321msg_perr("WARNING: No chipset found. Flash detection "
322 "will most likely fail.\n");
323} else if (ret == ERROR_FATAL)
324return ret;
325
326#if IS_X86
327/* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
328 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
329init_superio_ite();
330
331if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
332msg_perr("Aborting to be safe.\n");
333return 1;
334}
335#endif
336
337#if IS_X86 || IS_MIPS
338register_par_master(&par_master_internal, internal_buses_supported);
339return 0;
340#else
341msg_perr("Your platform is not supported yet for the internal "
342 "programmer due to missing\n"
343 "flash_base and top/bottom alignment information.\n"
344 "Aborting.\n");
345return 1;
346#endif
347#else
348/* FIXME: Remove this unconditional abort once all PCI drivers are
349 * converted to use little-endian accesses for memory BARs.
350 */
351msg_perr("Your platform is not supported yet for the internal "
352 "programmer because it has\n"
353 "not been converted from native endian to little endian "
354 "access yet.\n"
355 "Aborting.\n");
356return 1;
357#endif
358}
359#endif
360
361static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
362 chipaddr addr)
363{
364mmio_writeb(val, (void *) addr);
365}
366
367static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
368 chipaddr addr)
369{
370mmio_writew(val, (void *) addr);
371}
372
373static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
374 chipaddr addr)
375{
376mmio_writel(val, (void *) addr);
377}
378
379static uint8_t internal_chip_readb(const struct flashctx *flash,
380 const chipaddr addr)
381{
382return mmio_readb((void *) addr);
383}
384
385static uint16_t internal_chip_readw(const struct flashctx *flash,
386 const chipaddr addr)
387{
388return mmio_readw((void *) addr);
389}
390
391static uint32_t internal_chip_readl(const struct flashctx *flash,
392 const chipaddr addr)
393{
394return mmio_readl((void *) addr);
395}
396
397static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
398const chipaddr addr, size_t len)
399{
400mmio_readn((void *)addr, buf, len);
401return;
402}

Archive Download this file

Revision: HEAD