source: trunk/internal.c

Last change on this file was 1650, checked in by stefanct, 3 months ago

Add a bunch of new/tested stuff and various small changes 17.

Tested Mainboards:
OK:

NOT OK:

Tested flash chips:

Miscellaneous:

  • Fix superflouos line breaks in wiki mainboard and laptop output.
  • Use the .nh (no hyphenation) command in the manpage to enforce single-line URLs where useful.
  • Reference the manpage (besides the Laptops wiki page) in the laptop warning.
  • Minor output and whitespace fixes.
  • Add Fidelix IDs.
  • Add ISSE clones of PMC chips.
  • Fix typo: EMST -> ESMT.
  • Add ID of ESMT F25D08QA.
  • Refine GigaDevice? GD25Q series (missing voltages and comments).
  • Use underscore instead of lower-case x as wildcard in Sharp chip names.

Signed-off-by: Stefan Tauner <stefan.tauner@…>
Acked-by: Stefan Tauner <stefan.tauner@…>

File size: 11.2 KB
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 <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{
31        struct pci_dev *temp;
32
33        for (temp = pacc->devices; temp; temp = temp->next)
34                if (pci_filter_match(&filter, temp))
35                        return temp;
36
37        return NULL;
38}
39
40struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
41{
42        struct pci_dev *temp;
43        struct pci_filter filter;
44        uint16_t tmp2;
45
46        pci_filter_init(NULL, &filter);
47        filter.vendor = vendor;
48
49        for (temp = pacc->devices; temp; temp = temp->next)
50                if (pci_filter_match(&filter, temp)) {
51                        /* Read PCI class */
52                        tmp2 = pci_read_word(temp, 0x0a);
53                        if (tmp2 == devclass)
54                                return temp;
55                }
56
57        return NULL;
58}
59
60struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
61{
62        struct pci_dev *temp;
63        struct pci_filter filter;
64
65        pci_filter_init(NULL, &filter);
66        filter.vendor = vendor;
67        filter.device = device;
68
69        for (temp = pacc->devices; temp; temp = temp->next)
70                if (pci_filter_match(&filter, temp))
71                        return temp;
72
73        return 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{
79        struct pci_dev *temp;
80        struct pci_filter filter;
81
82        pci_filter_init(NULL, &filter);
83        filter.vendor = vendor;
84        filter.device = device;
85
86        for (temp = pacc->devices; temp; temp = temp->next)
87                if (pci_filter_match(&filter, temp)) {
88                        if ((card_vendor ==
89                             pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
90                            && (card_device ==
91                                pci_read_word(temp, PCI_SUBSYSTEM_ID)))
92                                return temp;
93                }
94
95        return 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{
106        probe_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();
113        probe_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{
123        if (superio_count == SUPERIO_MAX_COUNT)
124                return 1;
125        superios[superio_count++] = s;
126        return 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,
147                                const chipaddr addr, size_t len);
148static const struct par_programmer par_programmer_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
161static int internal_shutdown(void *data)
162{
163        return 0;
164}
165
166int internal_init(void)
167{
168#if __FLASHROM_LITTLE_ENDIAN__
169        int ret = 0;
170#endif
171        int force_laptop = 0;
172        int not_a_laptop = 0;
173        const char *board_vendor = NULL;
174        const char *board_model = NULL;
175        const char *cb_vendor = NULL;
176        const char *cb_model = NULL;
177        char *arg;
178
179        arg = extract_programmer_param("boardenable");
180        if (arg && !strcmp(arg,"force")) {
181                force_boardenable = 1;
182        } else if (arg && !strlen(arg)) {
183                msg_perr("Missing argument for boardenable.\n");
184                free(arg);
185                return 1;
186        } else if (arg) {
187                msg_perr("Unknown argument for boardenable: %s\n", arg);
188                free(arg);
189                return 1;
190        }
191        free(arg);
192
193        arg = extract_programmer_param("boardmismatch");
194        if (arg && !strcmp(arg,"force")) {
195                force_boardmismatch = 1;
196        } else if (arg && !strlen(arg)) {
197                msg_perr("Missing argument for boardmismatch.\n");
198                free(arg);
199                return 1;
200        } else if (arg) {
201                msg_perr("Unknown argument for boardmismatch: %s\n", arg);
202                free(arg);
203                return 1;
204        }
205        free(arg);
206
207        arg = extract_programmer_param("laptop");
208        if (arg && !strcmp(arg, "force_I_want_a_brick"))
209                force_laptop = 1;
210        else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
211                not_a_laptop = 1;
212        else if (arg && !strlen(arg)) {
213                msg_perr("Missing argument for laptop.\n");
214                free(arg);
215                return 1;
216        } else if (arg) {
217                msg_perr("Unknown argument for laptop: %s\n", arg);
218                free(arg);
219                return 1;
220        }
221        free(arg);
222
223        arg = extract_programmer_param("mainboard");
224        if (arg && strlen(arg)) {
225                if (board_parse_parameter(arg, &board_vendor, &board_model)) {
226                        free(arg);
227                        return 1;
228                }
229        } else if (arg && !strlen(arg)) {
230                msg_perr("Missing argument for mainboard.\n");
231                free(arg);
232                return 1;
233        }
234        free(arg);
235
236        if (rget_io_perms())
237                return 1;
238        if (register_shutdown(internal_shutdown, NULL))
239                return 1;
240
241        /* Default to Parallel/LPC/FWH flash devices. If a known host controller
242         * is found, the host controller init routine sets the
243         * internal_buses_supported bitfield.
244         */
245        internal_buses_supported = BUS_NONSPI;
246
247        /* Initialize PCI access for flash enables */
248        if (pci_init_common() != 0)
249                return 1;
250
251        if (processor_flash_enable()) {
252                msg_perr("Processor detection/init failed.\n"
253                         "Aborting.\n");
254                return 1;
255        }
256
257#if defined(__i386__) || defined(__x86_64__)
258        if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
259                if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
260                        msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
261                                  "         match the current coreboot IDs of the mainboard (%s:%s).\n",
262                                  board_vendor, board_model, cb_vendor, cb_model);
263                        if (!force_boardmismatch)
264                                return 1;
265                        msg_pinfo("Continuing anyway.\n");
266                }
267        }
268
269        dmi_init();
270
271        /* In case Super I/O probing would cause pretty explosions. */
272        board_handle_before_superio();
273
274        /* Probe for the Super I/O chip and fill global struct superio. */
275        probe_superio();
276#else
277        /* FIXME: Enable cbtable searching on all non-x86 platforms supported
278         *        by coreboot.
279         * FIXME: Find a replacement for DMI on non-x86.
280         * FIXME: Enable Super I/O probing once port I/O is possible.
281         */
282#endif
283
284        /* Check laptop whitelist. */
285        board_handle_before_laptop();
286
287        /* Warn if a non-whitelisted laptop is detected. */
288        if (is_laptop && !laptop_ok) {
289                msg_perr("========================================================================\n");
290                if (is_laptop == 1) {
291                        msg_perr("WARNING! You seem to be running flashrom on an unsupported laptop.\n");
292                } else {
293                        msg_perr("WARNING! You may be running flashrom on an unsupported laptop. We could\n"
294                                 "not detect this for sure because your vendor has not setup the SMBIOS\n"
295                                 "tables correctly. You can enforce execution by adding\n"
296                                 "'-p internal:laptop=this_is_not_a_laptop' to the command line, but\n"
297                                 "please read the following warning if you are not sure.\n\n");
298                }
299                msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
300                         "recommend to use the vendor flashing utility. The embedded controller\n"
301                         "(EC) in these machines often interacts badly with flashing.\n"
302                         "See the manpage and http://www.flashrom.org/Laptops for details.\n\n"
303                         "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
304                         "and write may brick your laptop.\n"
305                         "Read and probe may irritate your EC and cause fan failure, backlight\n"
306                         "failure and sudden poweroff.\n"
307                         "You have been warned.\n"
308                         "========================================================================\n");
309
310                if (force_laptop || (not_a_laptop && (is_laptop == 2))) {
311                        msg_perr("Proceeding anyway because user forced us to.\n");
312                } else {
313                        msg_perr("Aborting.\n");
314                        return 1;
315                }
316        }
317
318#if __FLASHROM_LITTLE_ENDIAN__
319        /* try to enable it. Failure IS an option, since not all motherboards
320         * really need this to be done, etc., etc.
321         */
322        ret = chipset_flash_enable();
323        if (ret == -2) {
324                msg_perr("WARNING: No chipset found. Flash detection "
325                         "will most likely fail.\n");
326        } else if (ret == ERROR_FATAL)
327                return ret;
328
329#if defined(__i386__) || defined(__x86_64__)
330        /* Probe unconditionally for IT87* LPC->SPI translation and for
331         * IT87* Parallel write enable.
332         */
333        init_superio_ite();
334#endif
335
336        if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
337                msg_perr("Aborting to be safe.\n");
338                return 1;
339        }
340
341#if defined(__i386__) || defined(__x86_64__) || defined (__mips)
342        register_par_programmer(&par_programmer_internal, internal_buses_supported);
343        return 0;
344#else
345        msg_perr("Your platform is not supported yet for the internal "
346                 "programmer due to missing\n"
347                 "flash_base and top/bottom alignment information.\n"
348                 "Aborting.\n");
349        return 1;
350#endif
351#else
352        /* FIXME: Remove this unconditional abort once all PCI drivers are
353         * converted to use little-endian accesses for memory BARs.
354         */
355        msg_perr("Your platform is not supported yet for the internal "
356                 "programmer because it has\n"
357                 "not been converted from native endian to little endian "
358                 "access yet.\n"
359                 "Aborting.\n");
360        return 1;
361#endif
362}
363#endif
364
365static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
366                                 chipaddr addr)
367{
368        mmio_writeb(val, (void *) addr);
369}
370
371static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
372                                 chipaddr addr)
373{
374        mmio_writew(val, (void *) addr);
375}
376
377static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
378                                 chipaddr addr)
379{
380        mmio_writel(val, (void *) addr);
381}
382
383static uint8_t internal_chip_readb(const struct flashctx *flash,
384                                   const chipaddr addr)
385{
386        return mmio_readb((void *) addr);
387}
388
389static uint16_t internal_chip_readw(const struct flashctx *flash,
390                                    const chipaddr addr)
391{
392        return mmio_readw((void *) addr);
393}
394
395static uint32_t internal_chip_readl(const struct flashctx *flash,
396                                    const chipaddr addr)
397{
398        return mmio_readl((void *) addr);
399}
400
401static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
402                                const chipaddr addr, size_t len)
403{
404        mmio_readn((void *)addr, buf, len);
405        return;
406}
Note: See TracBrowser for help on using the repository browser.