blob: 188fd5d6351b0758f5547cb98f15193bf295e955 [file] [log] [blame]
hailfingerabe249e2009-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.
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 <stdint.h>
22#include <string.h>
23#include <stdlib.h>
hailfingerabe249e2009-05-08 17:43:22 +000024#include <sys/types.h>
hailfingerabe249e2009-05-08 17:43:22 +000025#include "flash.h"
26
hailfinger80422e22009-12-13 22:28:00 +000027#if NEED_PCI == 1
uwe6934c4a2009-05-14 18:57:26 +000028struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
29{
30 struct pci_dev *temp;
31
32 for (temp = pacc->devices; temp; temp = temp->next)
33 if (pci_filter_match(&filter, temp))
34 return temp;
35
36 return NULL;
37}
38
hailfinger07e3ce02009-11-15 17:13:29 +000039struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
40{
41 struct pci_dev *temp;
42 struct pci_filter filter;
43 uint16_t tmp2;
44
45 pci_filter_init(NULL, &filter);
46 filter.vendor = vendor;
47
48 for (temp = pacc->devices; temp; temp = temp->next)
49 if (pci_filter_match(&filter, temp)) {
50 /* Read PCI class */
51 tmp2 = pci_read_word(temp, 0x0a);
52 if (tmp2 == class)
53 return temp;
54 }
55
56 return NULL;
57}
58
hailfingerabe249e2009-05-08 17:43:22 +000059struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
60{
61 struct pci_dev *temp;
62 struct pci_filter filter;
63
64 pci_filter_init(NULL, &filter);
65 filter.vendor = vendor;
66 filter.device = device;
67
68 for (temp = pacc->devices; temp; temp = temp->next)
69 if (pci_filter_match(&filter, temp))
70 return temp;
71
72 return NULL;
73}
74
75struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
76 uint16_t card_vendor, uint16_t card_device)
77{
78 struct pci_dev *temp;
79 struct pci_filter filter;
80
81 pci_filter_init(NULL, &filter);
82 filter.vendor = vendor;
83 filter.device = device;
84
85 for (temp = pacc->devices; temp; temp = temp->next)
86 if (pci_filter_match(&filter, temp)) {
87 if ((card_vendor ==
88 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
89 && (card_device ==
90 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
91 return temp;
92 }
93
94 return NULL;
95}
hailfinger80422e22009-12-13 22:28:00 +000096#endif
hailfingerabe249e2009-05-08 17:43:22 +000097
hailfinger90c7d542010-05-31 15:27:27 +000098#if CONFIG_INTERNAL == 1
mkarcherf2620582010-02-28 01:33:48 +000099int force_boardenable = 0;
hailfingerf4aaccc2010-04-28 15:22:14 +0000100int force_boardmismatch = 0;
hailfingerc236f9e2009-12-22 23:42:04 +0000101
hailfinger324a9cc2010-05-26 01:45:41 +0000102#if defined(__i386__) || defined(__x86_64__)
103struct superio superio = {};
104
hailfingerc236f9e2009-12-22 23:42:04 +0000105void probe_superio(void)
106{
107 superio = probe_superio_ite();
uwef6f94d42010-03-13 17:28:29 +0000108#if 0
109 /* Winbond Super I/O code is not yet available. */
hailfingerc236f9e2009-12-22 23:42:04 +0000110 if (superio.vendor == SUPERIO_VENDOR_NONE)
111 superio = probe_superio_winbond();
112#endif
113}
hailfinger324a9cc2010-05-26 01:45:41 +0000114#endif
hailfingerc236f9e2009-12-22 23:42:04 +0000115
hailfinger324a9cc2010-05-26 01:45:41 +0000116int is_laptop = 0;
mkarcher287aa242010-02-26 09:51:20 +0000117
uwebc526c82009-05-14 20:41:57 +0000118int internal_init(void)
119{
120 int ret = 0;
hailfingerf4aaccc2010-04-28 15:22:14 +0000121 int force_laptop = 0;
122 char *arg;
uwebc526c82009-05-14 20:41:57 +0000123
hailfinger1ef766d2010-07-06 09:55:48 +0000124 arg = extract_param(&programmer_param, "boardenable", ",:");
hailfingerf4aaccc2010-04-28 15:22:14 +0000125 if (arg && !strcmp(arg,"force")) {
126 force_boardenable = 1;
127 } else if (arg && !strlen(arg)) {
128 msg_perr("Missing argument for boardenable.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000129 free(arg);
130 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000131 } else if (arg) {
132 msg_perr("Unknown argument for boardenable: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000133 free(arg);
134 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000135 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000136 free(arg);
mkarcherf2620582010-02-28 01:33:48 +0000137
hailfinger1ef766d2010-07-06 09:55:48 +0000138 arg = extract_param(&programmer_param, "boardmismatch", ",:");
hailfingerf4aaccc2010-04-28 15:22:14 +0000139 if (arg && !strcmp(arg,"force")) {
140 force_boardmismatch = 1;
141 } else if (arg && !strlen(arg)) {
142 msg_perr("Missing argument for boardmismatch.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000143 free(arg);
144 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000145 } else if (arg) {
146 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000147 free(arg);
148 return 1;
mkarcherf2620582010-02-28 01:33:48 +0000149 }
hailfingerf4aaccc2010-04-28 15:22:14 +0000150 free(arg);
151
hailfinger1ef766d2010-07-06 09:55:48 +0000152 arg = extract_param(&programmer_param, "laptop", ",:");
hailfingerf4aaccc2010-04-28 15:22:14 +0000153 if (arg && !strcmp(arg,"force_I_want_a_brick")) {
154 force_laptop = 1;
155 } else if (arg && !strlen(arg)) {
156 msg_perr("Missing argument for laptop.\n");
hailfinger1ef766d2010-07-06 09:55:48 +0000157 free(arg);
158 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000159 } else if (arg) {
160 msg_perr("Unknown argument for laptop: %s\n", arg);
hailfinger1ef766d2010-07-06 09:55:48 +0000161 free(arg);
162 return 1;
hailfingerf4aaccc2010-04-28 15:22:14 +0000163 }
164 free(arg);
165
hailfinger0668eba2009-05-14 21:41:10 +0000166 get_io_perms();
hailfingerabe249e2009-05-08 17:43:22 +0000167
168 /* Initialize PCI access for flash enables */
169 pacc = pci_alloc(); /* Get the pci_access structure */
170 /* Set all options you want -- here we stick with the defaults */
171 pci_init(pacc); /* Initialize the PCI library */
172 pci_scan_bus(pacc); /* We want to get the list of devices */
173
hailfinger586f4ae2010-06-04 19:05:39 +0000174 if (processor_flash_enable()) {
175 msg_perr("Processor detection/init failed.\n"
176 "Aborting.\n");
177 return 1;
178 }
179
180#if defined(__i386__) || defined(__x86_64__)
181 /* We look at the cbtable first to see if we need a
hailfingerabe249e2009-05-08 17:43:22 +0000182 * mainboard specific flash enable sequence.
183 */
184 coreboot_init();
hailfinger324a9cc2010-05-26 01:45:41 +0000185
mkarcher803b4042010-01-20 14:14:11 +0000186 dmi_init();
hailfingerabe249e2009-05-08 17:43:22 +0000187
uwef6f94d42010-03-13 17:28:29 +0000188 /* Probe for the Super I/O chip and fill global struct superio. */
hailfingerc236f9e2009-12-22 23:42:04 +0000189 probe_superio();
hailfinger586f4ae2010-06-04 19:05:39 +0000190#else
191 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
192 * by coreboot.
193 * FIXME: Find a replacement for DMI on non-x86.
194 * FIXME: Enable Super I/O probing once port I/O is possible.
195 */
hailfinger324a9cc2010-05-26 01:45:41 +0000196#endif
hailfingerc236f9e2009-12-22 23:42:04 +0000197
uwef6f94d42010-03-13 17:28:29 +0000198 /* Warn if a laptop is detected. */
hailfingerf4aaccc2010-04-28 15:22:14 +0000199 if (is_laptop) {
200 msg_perr("========================================================================\n"
201 "WARNING! You seem to be running flashrom on a laptop.\n"
202 "Laptops, notebooks and netbooks are difficult to support and we recommend\n"
203 "to use the vendor flashing utility. The embedded controller (EC) in these\n"
204 "machines often interacts badly with flashing.\n"
205 "See http://www.flashrom.org/Laptops for details.\n\n"
206 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
207 "and write may brick your laptop.\n"
208 "Read and probe may irritate your EC and cause fan failure, backlight\n"
209 "failure and sudden poweroff.\n"
210 "You have been warned.\n"
211 "========================================================================\n");
212 if (force_laptop) {
213 msg_perr("Proceeding anyway because user specified "
214 "laptop=force_I_want_a_brick\n");
215 } else {
216 msg_perr("Aborting.\n");
217 exit(1);
218 }
219 }
mkarcher287aa242010-02-26 09:51:20 +0000220
hailfinger586f4ae2010-06-04 19:05:39 +0000221#if __FLASHROM_LITTLE_ENDIAN__
hailfingerabe249e2009-05-08 17:43:22 +0000222 /* try to enable it. Failure IS an option, since not all motherboards
223 * really need this to be done, etc., etc.
224 */
225 ret = chipset_flash_enable();
226 if (ret == -2) {
hailfingerf4aaccc2010-04-28 15:22:14 +0000227 msg_perr("WARNING: No chipset found. Flash detection "
228 "will most likely fail.\n");
hailfingerabe249e2009-05-08 17:43:22 +0000229 }
230
hailfinger324a9cc2010-05-26 01:45:41 +0000231#if defined(__i386__) || defined(__x86_64__)
hailfingerddd5d7b2010-03-25 02:50:40 +0000232 /* Probe for IT87* LPC->SPI translation unconditionally. */
233 it87xx_probe_spi_flash(NULL);
hailfinger324a9cc2010-05-26 01:45:41 +0000234#endif
hailfingerddd5d7b2010-03-25 02:50:40 +0000235
hailfingerabe249e2009-05-08 17:43:22 +0000236 board_flash_enable(lb_vendor, lb_part);
237
hailfinger681638b2009-09-02 13:43:56 +0000238 /* Even if chipset init returns an error code, we don't want to abort.
239 * The error code might have been a warning only.
240 * Besides that, we don't check the board enable return code either.
241 */
hailfinger586f4ae2010-06-04 19:05:39 +0000242#if defined(__i386__) || defined(__x86_64__)
hailfingerf4aaccc2010-04-28 15:22:14 +0000243 return 0;
hailfinger586f4ae2010-06-04 19:05:39 +0000244#else
245 msg_perr("Your platform is not supported yet for the internal "
246 "programmer due to missing\n"
247 "flash_base and top/bottom alignment information.\n"
248 "Aborting.\n");
249 return 1;
250#endif
251#else
252 /* FIXME: Remove this unconditional abort once all PCI drivers are
253 * converted to use little-endian accesses for memory BARs.
254 */
255 msg_perr("Your platform is not supported yet for the internal "
256 "programmer because it has\n"
257 "not been converted from native endian to little endian "
258 "access yet.\n"
259 "Aborting.\n");
260 return 1;
261#endif
hailfingerabe249e2009-05-08 17:43:22 +0000262}
263
264int internal_shutdown(void)
265{
hailfinger7828d092009-08-09 21:50:24 +0000266 release_io_perms();
hailfingerabe249e2009-05-08 17:43:22 +0000267
268 return 0;
269}
hailfinger80422e22009-12-13 22:28:00 +0000270#endif
hailfingerabe249e2009-05-08 17:43:22 +0000271
hailfinger82719632009-05-16 21:22:56 +0000272void internal_chip_writeb(uint8_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000273{
hailfinger38da6812009-05-17 15:49:24 +0000274 mmio_writeb(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000275}
276
hailfinger82719632009-05-16 21:22:56 +0000277void internal_chip_writew(uint16_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000278{
hailfinger38da6812009-05-17 15:49:24 +0000279 mmio_writew(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000280}
281
hailfinger82719632009-05-16 21:22:56 +0000282void internal_chip_writel(uint32_t val, chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000283{
hailfinger38da6812009-05-17 15:49:24 +0000284 mmio_writel(val, (void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000285}
286
hailfinger82719632009-05-16 21:22:56 +0000287uint8_t internal_chip_readb(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000288{
hailfinger38da6812009-05-17 15:49:24 +0000289 return mmio_readb((void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000290}
291
hailfinger82719632009-05-16 21:22:56 +0000292uint16_t internal_chip_readw(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000293{
hailfinger38da6812009-05-17 15:49:24 +0000294 return mmio_readw((void *) addr);
hailfingerabe249e2009-05-08 17:43:22 +0000295}
296
hailfinger82719632009-05-16 21:22:56 +0000297uint32_t internal_chip_readl(const chipaddr addr)
hailfingerabe249e2009-05-08 17:43:22 +0000298{
hailfinger38da6812009-05-17 15:49:24 +0000299 return mmio_readl((void *) addr);
300}
301
hailfinger9d987ef2009-06-05 18:32:07 +0000302void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
303{
304 memcpy(buf, (void *)addr, len);
305 return;
306}