internal.c 8.35 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2009 Carl-Daniel Hailfinger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <string.h>
#include <stdlib.h>
#include "flash.h"
24
#include "programmer.h"
25

26
#if NEED_PCI == 1
27 28 29 30 31 32 33 34 35 36 37
struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
{
	struct pci_dev *temp;

	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp))
			return temp;

	return NULL;
}

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
{
	struct pci_dev *temp;
	struct pci_filter filter;
	uint16_t tmp2;

	pci_filter_init(NULL, &filter);
	filter.vendor = vendor;

	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp)) {
			/* Read PCI class */
			tmp2 = pci_read_word(temp, 0x0a);
			if (tmp2 == class)
				return temp;
		}

	return NULL;
}

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
{
	struct pci_dev *temp;
	struct pci_filter filter;

	pci_filter_init(NULL, &filter);
	filter.vendor = vendor;
	filter.device = device;

	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp))
			return temp;

	return NULL;
}

struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
			      uint16_t card_vendor, uint16_t card_device)
{
	struct pci_dev *temp;
	struct pci_filter filter;

	pci_filter_init(NULL, &filter);
	filter.vendor = vendor;
	filter.device = device;

	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp)) {
			if ((card_vendor ==
			     pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
			    && (card_device ==
				pci_read_word(temp, PCI_SUBSYSTEM_ID)))
				return temp;
		}

	return NULL;
}
95
#endif
96

97
#if CONFIG_INTERNAL == 1
98
int force_boardenable = 0;
99
int force_boardmismatch = 0;
100

101
#if defined(__i386__) || defined(__x86_64__)
102 103
void probe_superio(void)
{
104
	probe_superio_ite();
105 106
#if 0
	/* Winbond Super I/O code is not yet available. */
107 108 109 110
	if (superio.vendor == SUPERIO_VENDOR_NONE)
		superio = probe_superio_winbond();
#endif
}
111 112 113 114 115 116 117 118 119 120 121 122 123 124

int superio_count = 0;
#define SUPERIO_MAX_COUNT 3

struct superio superios[SUPERIO_MAX_COUNT];

int register_superio(struct superio s)
{
	if (superio_count == SUPERIO_MAX_COUNT)
		return 1;
	superios[superio_count++] = s;
	return 0;
}

125
#endif
126

127
int is_laptop = 0;
128
int laptop_ok = 0;
Michael Karcher's avatar
Michael Karcher committed
129

130 131
int internal_init(void)
{
132
#if __FLASHROM_LITTLE_ENDIAN__
133
	int ret = 0;
134
#endif
135 136 137
	int force_laptop = 0;
	char *arg;

138
	arg = extract_programmer_param("boardenable");
139 140 141 142
	if (arg && !strcmp(arg,"force")) {
		force_boardenable = 1;
	} else if (arg && !strlen(arg)) {
		msg_perr("Missing argument for boardenable.\n");
143 144
		free(arg);
		return 1;
145 146
	} else if (arg) {
		msg_perr("Unknown argument for boardenable: %s\n", arg);
147 148
		free(arg);
		return 1;
149 150 151
	}
	free(arg);

152
	arg = extract_programmer_param("boardmismatch");
153 154 155 156
	if (arg && !strcmp(arg,"force")) {
		force_boardmismatch = 1;
	} else if (arg && !strlen(arg)) {
		msg_perr("Missing argument for boardmismatch.\n");
157 158
		free(arg);
		return 1;
159 160
	} else if (arg) {
		msg_perr("Unknown argument for boardmismatch: %s\n", arg);
161 162
		free(arg);
		return 1;
163
	}
164 165
	free(arg);

166
	arg = extract_programmer_param("laptop");
167 168 169 170
	if (arg && !strcmp(arg,"force_I_want_a_brick")) {
		force_laptop = 1;
	} else if (arg && !strlen(arg)) {
		msg_perr("Missing argument for laptop.\n");
171 172
		free(arg);
		return 1;
173 174
	} else if (arg) {
		msg_perr("Unknown argument for laptop: %s\n", arg);
175 176
		free(arg);
		return 1;
177
	}
178 179
	free(arg);

180
	get_io_perms();
181

182 183 184 185 186
	/* Default to Parallel/LPC/FWH flash devices. If a known host controller
	 * is found, the init routine sets the buses_supported bitfield.
	 */
	buses_supported = CHIP_BUSTYPE_NONSPI;

187 188 189 190 191 192
	/* Initialize PCI access for flash enables */
	pacc = pci_alloc();	/* Get the pci_access structure */
	/* Set all options you want -- here we stick with the defaults */
	pci_init(pacc);		/* Initialize the PCI library */
	pci_scan_bus(pacc);	/* We want to get the list of devices */

193 194 195 196 197 198 199 200
	if (processor_flash_enable()) {
		msg_perr("Processor detection/init failed.\n"
			 "Aborting.\n");
		return 1;
	}

#if defined(__i386__) || defined(__x86_64__)
	/* We look at the cbtable first to see if we need a
201 202 203
	 * mainboard specific flash enable sequence.
	 */
	coreboot_init();
204

Michael Karcher's avatar
Michael Karcher committed
205
	dmi_init();
206

207 208 209
	/* In case Super I/O probing would cause pretty explosions. */
	board_handle_before_superio();

210
	/* Probe for the Super I/O chip and fill global struct superio. */
211
	probe_superio();
212 213 214 215 216 217
#else
	/* FIXME: Enable cbtable searching on all non-x86 platforms supported
	 *        by coreboot.
	 * FIXME: Find a replacement for DMI on non-x86.
	 * FIXME: Enable Super I/O probing once port I/O is possible.
	 */
218
#endif
219

220 221 222 223 224
	/* Check laptop whitelist. */
	board_handle_before_laptop();

	/* Warn if a non-whitelisted laptop is detected. */
	if (is_laptop && !laptop_ok) {
225
		msg_perr("========================================================================\n"
226
			 "WARNING! You seem to be running flashrom on an unsupported laptop.\n"
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
			 "Laptops, notebooks and netbooks are difficult to support and we recommend\n"
			 "to use the vendor flashing utility. The embedded controller (EC) in these\n"
			 "machines often interacts badly with flashing.\n"
			 "See http://www.flashrom.org/Laptops for details.\n\n"
			 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
			 "and write may brick your laptop.\n"
			 "Read and probe may irritate your EC and cause fan failure, backlight\n"
			 "failure and sudden poweroff.\n"
			 "You have been warned.\n"
			 "========================================================================\n");
		if (force_laptop) {
			msg_perr("Proceeding anyway because user specified "
				 "laptop=force_I_want_a_brick\n");
		} else {
			msg_perr("Aborting.\n");
			exit(1);
		}
	}
Michael Karcher's avatar
Michael Karcher committed
245

246
#if __FLASHROM_LITTLE_ENDIAN__
247 248 249 250 251
	/* try to enable it. Failure IS an option, since not all motherboards
	 * really need this to be done, etc., etc.
	 */
	ret = chipset_flash_enable();
	if (ret == -2) {
252 253
		msg_perr("WARNING: No chipset found. Flash detection "
			 "will most likely fail.\n");
254 255
	}

256
#if defined(__i386__) || defined(__x86_64__)
257 258 259 260
	/* Probe unconditionally for IT87* LPC->SPI translation and for
	 * IT87* Parallel write enable.
	 */
	init_superio_ite();
261
#endif
262

263 264
	board_flash_enable(lb_vendor, lb_part);

265 266 267 268
	/* Even if chipset init returns an error code, we don't want to abort.
	 * The error code might have been a warning only.
	 * Besides that, we don't check the board enable return code either.
	 */
269
#if defined(__i386__) || defined(__x86_64__) || defined (__mips)
270
	return 0;
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
#else
	msg_perr("Your platform is not supported yet for the internal "
		 "programmer due to missing\n"
		 "flash_base and top/bottom alignment information.\n"
		 "Aborting.\n");
	return 1;
#endif
#else
	/* FIXME: Remove this unconditional abort once all PCI drivers are
	 * converted to use little-endian accesses for memory BARs.
	 */
	msg_perr("Your platform is not supported yet for the internal "
		 "programmer because it has\n"
		 "not been converted from native endian to little endian "
		 "access yet.\n"
		 "Aborting.\n");
	return 1;
#endif
289 290 291 292
}

int internal_shutdown(void)
{
293
	release_io_perms();
294 295 296

	return 0;
}
297
#endif
298

299
void internal_chip_writeb(uint8_t val, chipaddr addr)
300
{
301
	mmio_writeb(val, (void *) addr);
302 303
}

304
void internal_chip_writew(uint16_t val, chipaddr addr)
305
{
306
	mmio_writew(val, (void *) addr);
307 308
}

309
void internal_chip_writel(uint32_t val, chipaddr addr)
310
{
311
	mmio_writel(val, (void *) addr);
312 313
}

314
uint8_t internal_chip_readb(const chipaddr addr)
315
{
316
	return mmio_readb((void *) addr);
317 318
}

319
uint16_t internal_chip_readw(const chipaddr addr)
320
{
321
	return mmio_readw((void *) addr);
322 323
}

324
uint32_t internal_chip_readl(const chipaddr addr)
325 326 327 328
{
	return mmio_readl((void *) addr);
}

329 330 331 332 333
void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
{
	memcpy(buf, (void *)addr, len);
	return;
}