source: trunk/internal.c @ 1533

Revision 1533, 10.9 KB checked in by hailfinger, 2 weeks ago (diff)

Add Winbond W836xx SuperI/O detection.
Add ITE IT8707F/IT8710F detection.

Note that we autodetect those chips, but we don't handle their flash
translation features automatically yet.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@…>
Acked-by: Michael Karcher <flashrom@…>

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