mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Merge branch 'master' of git://git.denx.de/u-boot-x86
This commit is contained in:
		
						commit
						ab92da9f47
					
				@ -16,7 +16,6 @@
 | 
			
		||||
obj-y += car.o
 | 
			
		||||
obj-y += coreboot.o
 | 
			
		||||
obj-y += tables.o
 | 
			
		||||
obj-y += ipchecksum.o
 | 
			
		||||
obj-y += sdram.o
 | 
			
		||||
obj-y += timestamp.o
 | 
			
		||||
obj-$(CONFIG_PCI) += pci.o
 | 
			
		||||
 | 
			
		||||
@ -99,3 +99,8 @@ void panic_puts(const char *str)
 | 
			
		||||
	while (*str)
 | 
			
		||||
		NS16550_putc(port, *str++);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int misc_init_r(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,55 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the libpayload project.
 | 
			
		||||
 *
 | 
			
		||||
 * It has originally been taken from the FreeBSD project.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
 | 
			
		||||
 * Copyright (c) 2008 coresystems GmbH
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
#include <asm/arch/ipchecksum.h>
 | 
			
		||||
 | 
			
		||||
unsigned short ipchksum(const void *vptr, unsigned long nbytes)
 | 
			
		||||
{
 | 
			
		||||
	int sum, oddbyte;
 | 
			
		||||
	const unsigned short *ptr = vptr;
 | 
			
		||||
 | 
			
		||||
	sum = 0;
 | 
			
		||||
	while (nbytes > 1) {
 | 
			
		||||
		sum += *ptr++;
 | 
			
		||||
		nbytes -= 2;
 | 
			
		||||
	}
 | 
			
		||||
	if (nbytes == 1) {
 | 
			
		||||
		oddbyte = 0;
 | 
			
		||||
		((u8 *)&oddbyte)[0] = *(u8 *) ptr;
 | 
			
		||||
		((u8 *)&oddbyte)[1] = 0;
 | 
			
		||||
		sum += oddbyte;
 | 
			
		||||
	}
 | 
			
		||||
	sum = (sum >> 16) + (sum & 0xffff);
 | 
			
		||||
	sum += (sum >> 16);
 | 
			
		||||
	return ~sum;
 | 
			
		||||
}
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <asm/arch/ipchecksum.h>
 | 
			
		||||
#include <net.h>
 | 
			
		||||
#include <asm/arch/sysinfo.h>
 | 
			
		||||
#include <asm/arch/tables.h>
 | 
			
		||||
 | 
			
		||||
@ -131,11 +131,11 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Make sure the checksums match. */
 | 
			
		||||
	if (ipchksum((u16 *) header, sizeof(*header)) != 0)
 | 
			
		||||
	if (!ip_checksum_ok(header, sizeof(*header)))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (ipchksum((u16 *) (ptr + sizeof(*header)),
 | 
			
		||||
		     header->table_bytes) != header->table_checksum)
 | 
			
		||||
	if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) !=
 | 
			
		||||
	    header->table_checksum)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* Now, walk the tables. */
 | 
			
		||||
 | 
			
		||||
@ -223,6 +223,11 @@ static bool has_cpuid(void)
 | 
			
		||||
	return flag_is_changeable_p(X86_EFLAGS_ID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool has_mtrr(void)
 | 
			
		||||
{
 | 
			
		||||
	return cpuid_edx(0x00000001) & (1 << 12) ? true : false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int build_vendor_name(char *vendor_name)
 | 
			
		||||
{
 | 
			
		||||
	struct cpuid_result result;
 | 
			
		||||
@ -318,6 +323,8 @@ int x86_cpu_init_f(void)
 | 
			
		||||
		gd->arch.x86_model = c.x86_model;
 | 
			
		||||
		gd->arch.x86_mask = c.x86_mask;
 | 
			
		||||
		gd->arch.x86_device = cpu.device;
 | 
			
		||||
 | 
			
		||||
		gd->arch.has_mtrr = has_mtrr();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -26,20 +26,6 @@ config CACHE_MRC_SIZE_KB
 | 
			
		||||
	int
 | 
			
		||||
	default 256
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_BASE
 | 
			
		||||
	hex
 | 
			
		||||
	default 0xff800000
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_LOCATION
 | 
			
		||||
	hex
 | 
			
		||||
	depends on !CHROMEOS
 | 
			
		||||
	default 0x1ec000
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_SIZE
 | 
			
		||||
	hex
 | 
			
		||||
	depends on !CHROMEOS
 | 
			
		||||
	default 0x10000
 | 
			
		||||
 | 
			
		||||
config DCACHE_RAM_BASE
 | 
			
		||||
	hex
 | 
			
		||||
	default 0xff7f0000
 | 
			
		||||
@ -64,20 +50,6 @@ config CACHE_MRC_SIZE_KB
 | 
			
		||||
	int
 | 
			
		||||
	default 512
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_BASE
 | 
			
		||||
	hex
 | 
			
		||||
	default 0xff800000
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_LOCATION
 | 
			
		||||
	hex
 | 
			
		||||
	depends on !CHROMEOS
 | 
			
		||||
	default 0x370000
 | 
			
		||||
 | 
			
		||||
config MRC_CACHE_SIZE
 | 
			
		||||
	hex
 | 
			
		||||
	depends on !CHROMEOS
 | 
			
		||||
	default 0x10000
 | 
			
		||||
 | 
			
		||||
config DCACHE_RAM_BASE
 | 
			
		||||
	hex
 | 
			
		||||
	default 0xff7e0000
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ obj-y += lpc.o
 | 
			
		||||
obj-y += me_status.o
 | 
			
		||||
obj-y += model_206ax.o
 | 
			
		||||
obj-y += microcode_intel.o
 | 
			
		||||
obj-y += mrccache.o
 | 
			
		||||
obj-y += northbridge.o
 | 
			
		||||
obj-y += pch.o
 | 
			
		||||
obj-y += pci.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										156
									
								
								arch/x86/cpu/ivybridge/mrccache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								arch/x86/cpu/ivybridge/mrccache.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,156 @@
 | 
			
		||||
/*
 | 
			
		||||
 * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2014 Google Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier:	GPL-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fdtdec.h>
 | 
			
		||||
#include <net.h>
 | 
			
		||||
#include <spi.h>
 | 
			
		||||
#include <spi_flash.h>
 | 
			
		||||
#include <asm/arch/mrccache.h>
 | 
			
		||||
#include <asm/arch/sandybridge.h>
 | 
			
		||||
 | 
			
		||||
static struct mrc_data_container *next_mrc_block(
 | 
			
		||||
	struct mrc_data_container *mrc_cache)
 | 
			
		||||
{
 | 
			
		||||
	/* MRC data blocks are aligned within the region */
 | 
			
		||||
	u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
 | 
			
		||||
	if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
 | 
			
		||||
		mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
 | 
			
		||||
		mrc_size += MRC_DATA_ALIGN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u8 *region_ptr = (u8 *)mrc_cache;
 | 
			
		||||
	region_ptr += mrc_size;
 | 
			
		||||
	return (struct mrc_data_container *)region_ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_mrc_cache(struct mrc_data_container *cache)
 | 
			
		||||
{
 | 
			
		||||
	return cache && (cache->signature == MRC_DATA_SIGNATURE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Find the largest index block in the MRC cache. Return NULL if none is
 | 
			
		||||
 * found.
 | 
			
		||||
 */
 | 
			
		||||
struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	struct mrc_data_container *cache, *next;
 | 
			
		||||
	ulong base_addr, end_addr;
 | 
			
		||||
	uint id;
 | 
			
		||||
 | 
			
		||||
	base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
 | 
			
		||||
	end_addr = base_addr + entry->length;
 | 
			
		||||
	cache = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Search for the last filled entry in the region */
 | 
			
		||||
	for (id = 0, next = (struct mrc_data_container *)base_addr;
 | 
			
		||||
	     is_mrc_cache(next);
 | 
			
		||||
	     id++) {
 | 
			
		||||
		cache = next;
 | 
			
		||||
		next = next_mrc_block(next);
 | 
			
		||||
		if ((ulong)next >= end_addr)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (id-- == 0) {
 | 
			
		||||
		debug("%s: No valid MRC cache found.\n", __func__);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Verify checksum */
 | 
			
		||||
	if (cache->checksum != compute_ip_checksum(cache->data,
 | 
			
		||||
						   cache->data_size)) {
 | 
			
		||||
		printf("%s: MRC cache checksum mismatch\n", __func__);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	debug("%s: picked entry %u from cache block\n", __func__, id);
 | 
			
		||||
 | 
			
		||||
	return cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * find_next_mrc_cache() - get next cache entry
 | 
			
		||||
 *
 | 
			
		||||
 * @entry:	MRC cache flash area
 | 
			
		||||
 * @cache:	Entry to start from
 | 
			
		||||
 *
 | 
			
		||||
 * @return next cache entry if found, NULL if we got to the end
 | 
			
		||||
 */
 | 
			
		||||
static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry,
 | 
			
		||||
		struct mrc_data_container *cache)
 | 
			
		||||
{
 | 
			
		||||
	ulong base_addr, end_addr;
 | 
			
		||||
 | 
			
		||||
	base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
 | 
			
		||||
	end_addr = base_addr + entry->length;
 | 
			
		||||
 | 
			
		||||
	cache = next_mrc_block(cache);
 | 
			
		||||
	if ((ulong)cache >= end_addr) {
 | 
			
		||||
		/* Crossed the boundary */
 | 
			
		||||
		cache = NULL;
 | 
			
		||||
		debug("%s: no available entries found\n", __func__);
 | 
			
		||||
	} else {
 | 
			
		||||
		debug("%s: picked next entry from cache block at %p\n",
 | 
			
		||||
		      __func__, cache);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
 | 
			
		||||
		    struct mrc_data_container *cur)
 | 
			
		||||
{
 | 
			
		||||
	struct mrc_data_container *cache;
 | 
			
		||||
	ulong offset;
 | 
			
		||||
	ulong base_addr;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/* Find the last used block */
 | 
			
		||||
	base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
 | 
			
		||||
	debug("Updating MRC cache data\n");
 | 
			
		||||
	cache = mrccache_find_current(entry);
 | 
			
		||||
	if (cache && (cache->data_size == cur->data_size) &&
 | 
			
		||||
	    (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
 | 
			
		||||
		debug("MRC data in flash is up to date. No update\n");
 | 
			
		||||
		return -EEXIST;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Move to the next block, which will be the first unused block */
 | 
			
		||||
	if (cache)
 | 
			
		||||
		cache = find_next_mrc_cache(entry, cache);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If we have got to the end, erase the entire mrc-cache area and start
 | 
			
		||||
	 * again at block 0.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!cache) {
 | 
			
		||||
		debug("Erasing the MRC cache region of %x bytes at %x\n",
 | 
			
		||||
		      entry->length, entry->offset);
 | 
			
		||||
 | 
			
		||||
		ret = spi_flash_erase(sf, entry->offset, entry->length);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			debug("Failed to erase flash region\n");
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
		cache = (struct mrc_data_container *)base_addr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Write the data out */
 | 
			
		||||
	offset = (ulong)cache - base_addr + entry->offset;
 | 
			
		||||
	debug("Write MRC cache update to flash at %lx\n", offset);
 | 
			
		||||
	ret = spi_flash_write(sf, offset, cur->data_size + sizeof(*cur), cur);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		debug("Failed to write to SPI flash\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -14,12 +14,17 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fdtdec.h>
 | 
			
		||||
#include <malloc.h>
 | 
			
		||||
#include <net.h>
 | 
			
		||||
#include <rtc.h>
 | 
			
		||||
#include <spi.h>
 | 
			
		||||
#include <spi_flash.h>
 | 
			
		||||
#include <asm/processor.h>
 | 
			
		||||
#include <asm/gpio.h>
 | 
			
		||||
#include <asm/global_data.h>
 | 
			
		||||
#include <asm/mtrr.h>
 | 
			
		||||
#include <asm/pci.h>
 | 
			
		||||
#include <asm/arch/me.h>
 | 
			
		||||
#include <asm/arch/mrccache.h>
 | 
			
		||||
#include <asm/arch/pei_data.h>
 | 
			
		||||
#include <asm/arch/pch.h>
 | 
			
		||||
#include <asm/post.h>
 | 
			
		||||
@ -27,6 +32,10 @@
 | 
			
		||||
 | 
			
		||||
DECLARE_GLOBAL_DATA_PTR;
 | 
			
		||||
 | 
			
		||||
#define CMOS_OFFSET_MRC_SEED		152
 | 
			
		||||
#define CMOS_OFFSET_MRC_SEED_S3		156
 | 
			
		||||
#define CMOS_OFFSET_MRC_SEED_CHK	160
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function looks for the highest region of memory lower than 4GB which
 | 
			
		||||
 * has enough space for U-Boot where U-Boot is aligned on a page boundary.
 | 
			
		||||
@ -80,6 +89,202 @@ void dram_init_banksize(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_mrc_entry(struct spi_flash **sfp, struct fmap_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	const void *blob = gd->fdt_blob;
 | 
			
		||||
	int node, spi_node, mrc_node;
 | 
			
		||||
	int upto;
 | 
			
		||||
 | 
			
		||||
	/* Find the flash chip within the SPI controller node */
 | 
			
		||||
	upto = 0;
 | 
			
		||||
	spi_node = fdtdec_next_alias(blob, "spi", COMPAT_INTEL_ICH_SPI, &upto);
 | 
			
		||||
	if (spi_node < 0)
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
	node = fdt_first_subnode(blob, spi_node);
 | 
			
		||||
	if (node < 0)
 | 
			
		||||
		return -ECHILD;
 | 
			
		||||
 | 
			
		||||
	/* Find the place where we put the MRC cache */
 | 
			
		||||
	mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
 | 
			
		||||
	if (mrc_node < 0)
 | 
			
		||||
		return -EPERM;
 | 
			
		||||
 | 
			
		||||
	if (fdtdec_read_fmap_entry(blob, mrc_node, "rm-mrc-cache", entry))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (sfp) {
 | 
			
		||||
		*sfp = spi_flash_probe_fdt(blob, node, spi_node);
 | 
			
		||||
		if (!*sfp)
 | 
			
		||||
			return -EBADF;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_seed_from_cmos(struct pei_data *pei_data)
 | 
			
		||||
{
 | 
			
		||||
	u16 c1, c2, checksum, seed_checksum;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Read scrambler seeds from CMOS RAM. We don't want to store them in
 | 
			
		||||
	 * SPI flash since they change on every boot and that would wear down
 | 
			
		||||
	 * the flash too much. So we store these in CMOS and the large MRC
 | 
			
		||||
	 * data in SPI flash.
 | 
			
		||||
	 */
 | 
			
		||||
	pei_data->scrambler_seed = rtc_read32(CMOS_OFFSET_MRC_SEED);
 | 
			
		||||
	debug("Read scrambler seed    0x%08x from CMOS 0x%02x\n",
 | 
			
		||||
	      pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
 | 
			
		||||
 | 
			
		||||
	pei_data->scrambler_seed_s3 = rtc_read32(CMOS_OFFSET_MRC_SEED_S3);
 | 
			
		||||
	debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n",
 | 
			
		||||
	      pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
 | 
			
		||||
 | 
			
		||||
	/* Compute seed checksum and compare */
 | 
			
		||||
	c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
 | 
			
		||||
				 sizeof(u32));
 | 
			
		||||
	c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
 | 
			
		||||
				 sizeof(u32));
 | 
			
		||||
	checksum = add_ip_checksums(sizeof(u32), c1, c2);
 | 
			
		||||
 | 
			
		||||
	seed_checksum = rtc_read8(CMOS_OFFSET_MRC_SEED_CHK);
 | 
			
		||||
	seed_checksum |= rtc_read8(CMOS_OFFSET_MRC_SEED_CHK + 1) << 8;
 | 
			
		||||
 | 
			
		||||
	if (checksum != seed_checksum) {
 | 
			
		||||
		debug("%s: invalid seed checksum\n", __func__);
 | 
			
		||||
		pei_data->scrambler_seed = 0;
 | 
			
		||||
		pei_data->scrambler_seed_s3 = 0;
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int prepare_mrc_cache(struct pei_data *pei_data)
 | 
			
		||||
{
 | 
			
		||||
	struct mrc_data_container *mrc_cache;
 | 
			
		||||
	struct fmap_entry entry;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = read_seed_from_cmos(pei_data);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
	ret = get_mrc_entry(NULL, &entry);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
	mrc_cache = mrccache_find_current(&entry);
 | 
			
		||||
	if (!mrc_cache)
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * TODO(sjg@chromium.org): Skip this for now as it causes boot
 | 
			
		||||
	 * problems
 | 
			
		||||
	 */
 | 
			
		||||
	if (0) {
 | 
			
		||||
		pei_data->mrc_input = mrc_cache->data;
 | 
			
		||||
		pei_data->mrc_input_len = mrc_cache->data_size;
 | 
			
		||||
	}
 | 
			
		||||
	debug("%s: at %p, size %x checksum %04x\n", __func__,
 | 
			
		||||
	      pei_data->mrc_input, pei_data->mrc_input_len,
 | 
			
		||||
	      mrc_cache->checksum);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int build_mrc_data(struct mrc_data_container **datap)
 | 
			
		||||
{
 | 
			
		||||
	struct mrc_data_container *data;
 | 
			
		||||
	int orig_len;
 | 
			
		||||
	int output_len;
 | 
			
		||||
 | 
			
		||||
	orig_len = gd->arch.mrc_output_len;
 | 
			
		||||
	output_len = ALIGN(orig_len, 16);
 | 
			
		||||
	data = malloc(output_len + sizeof(*data));
 | 
			
		||||
	if (!data)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	data->signature = MRC_DATA_SIGNATURE;
 | 
			
		||||
	data->data_size = output_len;
 | 
			
		||||
	data->reserved = 0;
 | 
			
		||||
	memcpy(data->data, gd->arch.mrc_output, orig_len);
 | 
			
		||||
 | 
			
		||||
	/* Zero the unused space in aligned buffer. */
 | 
			
		||||
	if (output_len > orig_len)
 | 
			
		||||
		memset(data->data + orig_len, 0, output_len - orig_len);
 | 
			
		||||
 | 
			
		||||
	data->checksum = compute_ip_checksum(data->data, output_len);
 | 
			
		||||
	*datap = data;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int write_seeds_to_cmos(struct pei_data *pei_data)
 | 
			
		||||
{
 | 
			
		||||
	u16 c1, c2, checksum;
 | 
			
		||||
 | 
			
		||||
	/* Save the MRC seed values to CMOS */
 | 
			
		||||
	rtc_write32(CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed);
 | 
			
		||||
	debug("Save scrambler seed    0x%08x to CMOS 0x%02x\n",
 | 
			
		||||
	      pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
 | 
			
		||||
 | 
			
		||||
	rtc_write32(CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3);
 | 
			
		||||
	debug("Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n",
 | 
			
		||||
	      pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
 | 
			
		||||
 | 
			
		||||
	/* Save a simple checksum of the seed values */
 | 
			
		||||
	c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed,
 | 
			
		||||
				 sizeof(u32));
 | 
			
		||||
	c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3,
 | 
			
		||||
				 sizeof(u32));
 | 
			
		||||
	checksum = add_ip_checksums(sizeof(u32), c1, c2);
 | 
			
		||||
 | 
			
		||||
	rtc_write8(CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff);
 | 
			
		||||
	rtc_write8(CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sdram_save_mrc_data(void)
 | 
			
		||||
{
 | 
			
		||||
	struct mrc_data_container *data;
 | 
			
		||||
	struct fmap_entry entry;
 | 
			
		||||
	struct spi_flash *sf;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!gd->arch.mrc_output_len)
 | 
			
		||||
		return 0;
 | 
			
		||||
	debug("Saving %d bytes of MRC output data to SPI flash\n",
 | 
			
		||||
	      gd->arch.mrc_output_len);
 | 
			
		||||
 | 
			
		||||
	ret = get_mrc_entry(&sf, &entry);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto err_entry;
 | 
			
		||||
	ret = build_mrc_data(&data);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		goto err_data;
 | 
			
		||||
	ret = mrccache_update(sf, &entry, data);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		debug("Saved MRC data with checksum %04x\n", data->checksum);
 | 
			
		||||
 | 
			
		||||
	free(data);
 | 
			
		||||
err_data:
 | 
			
		||||
	spi_flash_free(sf);
 | 
			
		||||
err_entry:
 | 
			
		||||
	if (ret)
 | 
			
		||||
		debug("%s: Failed: %d\n", __func__, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Use this hook to save our SDRAM parameters */
 | 
			
		||||
int misc_init_r(void)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = sdram_save_mrc_data();
 | 
			
		||||
	if (ret)
 | 
			
		||||
		printf("Unable to save MRC data: %d\n", ret);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *const ecc_decoder[] = {
 | 
			
		||||
	"inactive",
 | 
			
		||||
	"active on IO",
 | 
			
		||||
@ -142,6 +347,11 @@ static asmlinkage void console_tx_byte(unsigned char byte)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int recovery_mode_enabled(void)
 | 
			
		||||
{
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Find the PEI executable in the ROM and execute it.
 | 
			
		||||
 *
 | 
			
		||||
@ -166,6 +376,17 @@ int sdram_initialise(struct pei_data *pei_data)
 | 
			
		||||
 | 
			
		||||
	debug("Starting UEFI PEI System Agent\n");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Do not pass MRC data in for recovery mode boot,
 | 
			
		||||
	 * Always pass it in for S3 resume.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!recovery_mode_enabled() ||
 | 
			
		||||
	    pei_data->boot_mode == PEI_BOOT_RESUME) {
 | 
			
		||||
		ret = prepare_mrc_cache(pei_data);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			debug("prepare_mrc_cache failed: %d\n", ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If MRC data is not found we cannot continue S3 resume. */
 | 
			
		||||
	if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) {
 | 
			
		||||
		debug("Giving up in sdram_initialize: No MRC data\n");
 | 
			
		||||
@ -216,6 +437,8 @@ int sdram_initialise(struct pei_data *pei_data)
 | 
			
		||||
	debug("System Agent Version %d.%d.%d Build %d\n",
 | 
			
		||||
	      version >> 24 , (version >> 16) & 0xff,
 | 
			
		||||
	      (version >> 8) & 0xff, version & 0xff);
 | 
			
		||||
	debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len,
 | 
			
		||||
	      pei_data->mrc_output);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Send ME init done for SandyBridge here.  This is done inside the
 | 
			
		||||
@ -231,6 +454,36 @@ int sdram_initialise(struct pei_data *pei_data)
 | 
			
		||||
	post_system_agent_init(pei_data);
 | 
			
		||||
	report_memory_config();
 | 
			
		||||
 | 
			
		||||
	/* S3 resume: don't save scrambler seed or MRC data */
 | 
			
		||||
	if (pei_data->boot_mode != PEI_BOOT_RESUME) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * This will be copied to SDRAM in reserve_arch(), then written
 | 
			
		||||
		 * to SPI flash in sdram_save_mrc_data()
 | 
			
		||||
		 */
 | 
			
		||||
		gd->arch.mrc_output = (char *)pei_data->mrc_output;
 | 
			
		||||
		gd->arch.mrc_output_len = pei_data->mrc_output_len;
 | 
			
		||||
		ret = write_seeds_to_cmos(pei_data);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			debug("Failed to write seeds to CMOS: %d\n", ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int reserve_arch(void)
 | 
			
		||||
{
 | 
			
		||||
	u16 checksum;
 | 
			
		||||
 | 
			
		||||
	checksum = compute_ip_checksum(gd->arch.mrc_output,
 | 
			
		||||
				       gd->arch.mrc_output_len);
 | 
			
		||||
	debug("Saving %d bytes for MRC output data, checksum %04x\n",
 | 
			
		||||
	      gd->arch.mrc_output_len, checksum);
 | 
			
		||||
	gd->start_addr_sp -= gd->arch.mrc_output_len;
 | 
			
		||||
	memcpy((void *)gd->start_addr_sp, gd->arch.mrc_output,
 | 
			
		||||
	       gd->arch.mrc_output_len);
 | 
			
		||||
	gd->arch.mrc_output = (char *)gd->start_addr_sp;
 | 
			
		||||
	gd->start_addr_sp &= ~0xf;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,14 @@
 | 
			
		||||
#include <asm/msr.h>
 | 
			
		||||
#include <asm/mtrr.h>
 | 
			
		||||
 | 
			
		||||
DECLARE_GLOBAL_DATA_PTR;
 | 
			
		||||
 | 
			
		||||
/* Prepare to adjust MTRRs */
 | 
			
		||||
void mtrr_open(struct mtrr_state *state)
 | 
			
		||||
{
 | 
			
		||||
	if (!gd->arch.has_mtrr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	state->enable_cache = dcache_status();
 | 
			
		||||
 | 
			
		||||
	if (state->enable_cache)
 | 
			
		||||
@ -31,6 +36,9 @@ void mtrr_open(struct mtrr_state *state)
 | 
			
		||||
/* Clean up after adjusting MTRRs, and enable them */
 | 
			
		||||
void mtrr_close(struct mtrr_state *state)
 | 
			
		||||
{
 | 
			
		||||
	if (!gd->arch.has_mtrr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
 | 
			
		||||
	if (state->enable_cache)
 | 
			
		||||
		enable_caches();
 | 
			
		||||
@ -43,6 +51,9 @@ int mtrr_commit(bool do_caches)
 | 
			
		||||
	uint64_t mask;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (!gd->arch.has_mtrr)
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
 | 
			
		||||
	mtrr_open(&state);
 | 
			
		||||
	for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
 | 
			
		||||
		mask = ~(req->size - 1);
 | 
			
		||||
@ -64,6 +75,9 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size)
 | 
			
		||||
	struct mtrr_request *req;
 | 
			
		||||
	uint64_t mask;
 | 
			
		||||
 | 
			
		||||
	if (!gd->arch.has_mtrr)
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
 | 
			
		||||
	if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
 | 
			
		||||
		return -ENOSPC;
 | 
			
		||||
	req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  U-boot - x86 Startup Code
 | 
			
		||||
 *  U-Boot - x86 Startup Code
 | 
			
		||||
 *
 | 
			
		||||
 * (C) Copyright 2008-2011
 | 
			
		||||
 * Graeme Russ, <graeme.russ@gmail.com>
 | 
			
		||||
@ -28,7 +28,7 @@ start16:
 | 
			
		||||
	movl	$GD_FLG_COLD_BOOT, %ebx
 | 
			
		||||
 | 
			
		||||
	xorl	%eax, %eax
 | 
			
		||||
	movl	%eax, %cr3    /* Invalidate TLB */
 | 
			
		||||
	movl	%eax, %cr3	/* Invalidate TLB */
 | 
			
		||||
 | 
			
		||||
	/* Turn off cache (this might require a 486-class CPU) */
 | 
			
		||||
	movl	%cr0, %eax
 | 
			
		||||
@ -49,7 +49,7 @@ o32 cs	lgdt	gdt_ptr
 | 
			
		||||
	jmp	ff
 | 
			
		||||
ff:
 | 
			
		||||
 | 
			
		||||
	/* Finally restore BIST and jump to the 32bit initialization code */
 | 
			
		||||
	/* Finally restore BIST and jump to the 32-bit initialization code */
 | 
			
		||||
	movw	$code32start, %ax
 | 
			
		||||
	movw	%ax, %bp
 | 
			
		||||
	movl	%ecx, %eax
 | 
			
		||||
@ -64,17 +64,17 @@ idt_ptr:
 | 
			
		||||
	.word	0		/* limit */
 | 
			
		||||
	.long	0		/* base */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The following Global Descriptor Table is just enough to get us into
 | 
			
		||||
 * 'Flat Protected Mode' - It will be discarded as soon as the final
 | 
			
		||||
 * GDT is setup in a safe location in RAM
 | 
			
		||||
 */
 | 
			
		||||
	/*
 | 
			
		||||
	 * The following Global Descriptor Table is just enough to get us into
 | 
			
		||||
	 * 'Flat Protected Mode' - It will be discarded as soon as the final
 | 
			
		||||
	 * GDT is setup in a safe location in RAM
 | 
			
		||||
	 */
 | 
			
		||||
gdt_ptr:
 | 
			
		||||
	.word	0x1f		/* limit (31 bytes = 4 GDT entries - 1) */
 | 
			
		||||
	.long	BOOT_SEG + gdt	/* base */
 | 
			
		||||
 | 
			
		||||
/* Some CPUs are picky about GDT alignment... */
 | 
			
		||||
.align 16
 | 
			
		||||
	/* Some CPUs are picky about GDT alignment... */
 | 
			
		||||
	.align	16
 | 
			
		||||
gdt:
 | 
			
		||||
	/*
 | 
			
		||||
	 * The GDT table ...
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,10 @@
 | 
			
		||||
	model = "Google Link";
 | 
			
		||||
	compatible = "google,link", "intel,celeron-ivybridge";
 | 
			
		||||
 | 
			
		||||
	aliases {
 | 
			
		||||
		spi0 = "/spi";
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	config {
 | 
			
		||||
	       silent_console = <0>;
 | 
			
		||||
	};
 | 
			
		||||
@ -150,11 +154,20 @@
 | 
			
		||||
	spi {
 | 
			
		||||
		#address-cells = <1>;
 | 
			
		||||
		#size-cells = <0>;
 | 
			
		||||
		compatible = "intel,ich9";
 | 
			
		||||
		compatible = "intel,ich-spi";
 | 
			
		||||
		spi-flash@0 {
 | 
			
		||||
			#size-cells = <1>;
 | 
			
		||||
			#address-cells = <1>;
 | 
			
		||||
			reg = <0>;
 | 
			
		||||
			compatible = "winbond,w25q64", "spi-flash";
 | 
			
		||||
			memory-map = <0xff800000 0x00800000>;
 | 
			
		||||
			rw-mrc-cache {
 | 
			
		||||
				label = "rw-mrc-cache";
 | 
			
		||||
				/* Alignment: 4k (for updating) */
 | 
			
		||||
				reg = <0x003e0000 0x00010000>;
 | 
			
		||||
				type = "wiped";
 | 
			
		||||
				wipe-value = [ff];
 | 
			
		||||
			};
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,37 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the libpayload project.
 | 
			
		||||
 *
 | 
			
		||||
 * It has originally been taken from the FreeBSD project.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
 | 
			
		||||
 * Copyright (c) 2008 coresystems GmbH
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _COREBOOT_IPCHECKSUM_H
 | 
			
		||||
#define _COREBOOT_IPCHECKSUM_H
 | 
			
		||||
 | 
			
		||||
unsigned short ipchksum(const void *vptr, unsigned long nbytes);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										51
									
								
								arch/x86/include/asm/arch-ivybridge/mrccache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								arch/x86/include/asm/arch-ivybridge/mrccache.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 Google, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier:	GPL-2.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ASM_ARCH_MRCCACHE_H
 | 
			
		||||
#define _ASM_ARCH_MRCCACHE_H
 | 
			
		||||
 | 
			
		||||
#define MRC_DATA_ALIGN		0x1000
 | 
			
		||||
#define MRC_DATA_SIGNATURE	(('M' << 0) | ('R' << 8) | ('C' << 16) | \
 | 
			
		||||
					('D'<<24))
 | 
			
		||||
 | 
			
		||||
__packed struct mrc_data_container {
 | 
			
		||||
	u32	signature;	/* "MRCD" */
 | 
			
		||||
	u32	data_size;	/* Size of the 'data' field */
 | 
			
		||||
	u32	checksum;	/* IP style checksum */
 | 
			
		||||
	u32	reserved;	/* For header alignment */
 | 
			
		||||
	u8	data[0];	/* Variable size, platform/run time dependent */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fmap_entry;
 | 
			
		||||
struct spi_flash;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mrccache_find_current() - find the latest MRC cache record
 | 
			
		||||
 *
 | 
			
		||||
 * This searches the MRC cache region looking for the latest record to use
 | 
			
		||||
 * for setting up SDRAM
 | 
			
		||||
 *
 | 
			
		||||
 * @entry:	Information about the position and size of the MRC cache
 | 
			
		||||
 * @return pointer to latest record, or NULL if none
 | 
			
		||||
 */
 | 
			
		||||
struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * mrccache_update() - update the MRC cache with a new record
 | 
			
		||||
 *
 | 
			
		||||
 * This writes a new record to the end of the MRC cache. If the new record is
 | 
			
		||||
 * the same as the latest record then the write is skipped
 | 
			
		||||
 *
 | 
			
		||||
 * @sf:		SPI flash to write to
 | 
			
		||||
 * @entry:	Position and size of MRC cache in SPI flash
 | 
			
		||||
 * @cur:	Record to write
 | 
			
		||||
 * @return 0 if updated, -EEXIST if the record is the same as the latest
 | 
			
		||||
 * record, other error if SPI write failed
 | 
			
		||||
 */
 | 
			
		||||
int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
 | 
			
		||||
		    struct mrc_data_container *cur);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -44,11 +44,11 @@ struct mtrr_request {
 | 
			
		||||
 | 
			
		||||
/* Architecture-specific global data */
 | 
			
		||||
struct arch_global_data {
 | 
			
		||||
	struct global_data *gd_addr;		/* Location of Global Data */
 | 
			
		||||
	uint8_t  x86;			/* CPU family */
 | 
			
		||||
	uint8_t  x86_vendor;		/* CPU vendor */
 | 
			
		||||
	uint8_t  x86_model;
 | 
			
		||||
	uint8_t  x86_mask;
 | 
			
		||||
	struct global_data *gd_addr;	/* Location of Global Data */
 | 
			
		||||
	uint8_t x86;			/* CPU family */
 | 
			
		||||
	uint8_t x86_vendor;		/* CPU vendor */
 | 
			
		||||
	uint8_t x86_model;
 | 
			
		||||
	uint8_t x86_mask;
 | 
			
		||||
	uint32_t x86_device;
 | 
			
		||||
	uint64_t tsc_base;		/* Initial value returned by rdtsc() */
 | 
			
		||||
	uint32_t tsc_base_kclocks;	/* Initial tsc as a kclocks value */
 | 
			
		||||
@ -60,10 +60,14 @@ struct arch_global_data {
 | 
			
		||||
	const struct pch_gpio_map *gpio_map;	/* board GPIO map */
 | 
			
		||||
	struct memory_info meminfo;	/* Memory information */
 | 
			
		||||
#ifdef CONFIG_HAVE_FSP
 | 
			
		||||
	void	*hob_list;		/* FSP HOB list */
 | 
			
		||||
	void *hob_list;			/* FSP HOB list */
 | 
			
		||||
#endif
 | 
			
		||||
	struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
 | 
			
		||||
	int mtrr_req_count;
 | 
			
		||||
	int has_mtrr;
 | 
			
		||||
	/* MRC training data to save for the next boot */
 | 
			
		||||
	char *mrc_output;
 | 
			
		||||
	unsigned int mrc_output_len;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -65,7 +65,6 @@ void mtrr_open(struct mtrr_state *state);
 | 
			
		||||
 *
 | 
			
		||||
 * @state:	Structure from mtrr_open()
 | 
			
		||||
 */
 | 
			
		||||
/*  */
 | 
			
		||||
void mtrr_close(struct mtrr_state *state);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -76,6 +75,8 @@ void mtrr_close(struct mtrr_state *state);
 | 
			
		||||
 * @type:	Requested type (MTRR_TYPE_)
 | 
			
		||||
 * @start:	Start address
 | 
			
		||||
 * @size:	Size
 | 
			
		||||
 *
 | 
			
		||||
 * @return:	0 on success, non-zero on failure
 | 
			
		||||
 */
 | 
			
		||||
int mtrr_add_request(int type, uint64_t start, uint64_t size);
 | 
			
		||||
 | 
			
		||||
@ -86,6 +87,8 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size);
 | 
			
		||||
 * It must be called with caches disabled.
 | 
			
		||||
 *
 | 
			
		||||
 * @do_caches:	true if caches are currently on
 | 
			
		||||
 *
 | 
			
		||||
 * @return:	0 on success, non-zero on failure
 | 
			
		||||
 */
 | 
			
		||||
int mtrr_commit(bool do_caches);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -70,4 +70,6 @@ uint64_t timer_get_tsc(void);
 | 
			
		||||
 | 
			
		||||
void quick_ram_check(void);
 | 
			
		||||
 | 
			
		||||
#define PCI_VGA_RAM_IMAGE_START		0xc0000
 | 
			
		||||
 | 
			
		||||
#endif	/* _U_BOOT_I386_H_ */
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <fdtdec.h>
 | 
			
		||||
#include <spi.h>
 | 
			
		||||
#include <asm/errno.h>
 | 
			
		||||
#include <asm/mtrr.h>
 | 
			
		||||
#include <asm/sections.h>
 | 
			
		||||
 | 
			
		||||
@ -71,7 +72,8 @@ int init_cache_f_r(void)
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = mtrr_commit(false);
 | 
			
		||||
	if (ret)
 | 
			
		||||
	/* If MTRR MSR is not implemented by the processor, just ignore it */
 | 
			
		||||
	if (ret && ret != -ENOSYS)
 | 
			
		||||
		return ret;
 | 
			
		||||
#endif
 | 
			
		||||
	/* Initialise the CPU cache(s) */
 | 
			
		||||
 | 
			
		||||
@ -130,7 +130,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 | 
			
		||||
	printf("Interrupt-Information:\n");
 | 
			
		||||
	printf("Nr  Routine   Arg       Count\n");
 | 
			
		||||
 | 
			
		||||
	for (irq = 0; irq <= CONFIG_SYS_NUM_IRQS; irq++) {
 | 
			
		||||
	for (irq = 0; irq < CONFIG_SYS_NUM_IRQS; irq++) {
 | 
			
		||||
		if (irq_handlers[irq].handler != NULL) {
 | 
			
		||||
			printf("%02d  %08lx  %08lx  %d\n",
 | 
			
		||||
					irq,
 | 
			
		||||
 | 
			
		||||
@ -807,6 +807,12 @@ static int initf_dm(void)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Architecture-specific memory reservation */
 | 
			
		||||
__weak int reserve_arch(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static init_fnc_t init_sequence_f[] = {
 | 
			
		||||
#ifdef CONFIG_SANDBOX
 | 
			
		||||
	setup_ram_buf,
 | 
			
		||||
@ -970,6 +976,7 @@ static init_fnc_t init_sequence_f[] = {
 | 
			
		||||
	setup_machine,
 | 
			
		||||
	reserve_global_data,
 | 
			
		||||
	reserve_fdt,
 | 
			
		||||
	reserve_arch,
 | 
			
		||||
	reserve_stacks,
 | 
			
		||||
	setup_dram_config,
 | 
			
		||||
	show_dram_config,
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,6 @@ CONFIG_OF_SEPARATE=y
 | 
			
		||||
CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
 | 
			
		||||
CONFIG_HAVE_MRC=y
 | 
			
		||||
CONFIG_SMM_TSEG_SIZE=0x800000
 | 
			
		||||
CONFIG_VIDEO_X86=y
 | 
			
		||||
CONFIG_VIDEO_VESA=y
 | 
			
		||||
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
 | 
			
		||||
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
 | 
			
		||||
 | 
			
		||||
@ -62,40 +62,158 @@ static u32 saveBaseAddress14;
 | 
			
		||||
static u32 saveBaseAddress18;
 | 
			
		||||
static u32 saveBaseAddress20;
 | 
			
		||||
 | 
			
		||||
static void atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
 | 
			
		||||
				  struct vbe_mode_info *mode_info)
 | 
			
		||||
/* Addres im memory of VBE region */
 | 
			
		||||
const int vbe_offset = 0x2000;
 | 
			
		||||
 | 
			
		||||
static const void *bios_ptr(const void *buf, BE_VGAInfo *vga_info,
 | 
			
		||||
			    u32 x86_dword_ptr)
 | 
			
		||||
{
 | 
			
		||||
	u32 seg_ofs, flat;
 | 
			
		||||
 | 
			
		||||
	seg_ofs = le32_to_cpu(x86_dword_ptr);
 | 
			
		||||
	flat = ((seg_ofs & 0xffff0000) >> 12) | (seg_ofs & 0xffff);
 | 
			
		||||
	if (flat >= 0xc0000)
 | 
			
		||||
		return vga_info->BIOSImage + flat - 0xc0000;
 | 
			
		||||
	else
 | 
			
		||||
		return buf + (flat - vbe_offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs,
 | 
			
		||||
			      int vesa_mode, struct vbe_mode_info *mode_info)
 | 
			
		||||
{
 | 
			
		||||
	void *buffer = (void *)(M.mem_base + vbe_offset);
 | 
			
		||||
	u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
 | 
			
		||||
	u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
 | 
			
		||||
	struct vesa_mode_info *vm;
 | 
			
		||||
	struct vbe_info *info;
 | 
			
		||||
	const u16 *modes_bios, *ptr;
 | 
			
		||||
	u16 *modes;
 | 
			
		||||
	int size;
 | 
			
		||||
 | 
			
		||||
	debug("VBE: Getting information\n");
 | 
			
		||||
	regs->e.eax = VESA_GET_INFO;
 | 
			
		||||
	regs->e.esi = buffer_seg;
 | 
			
		||||
	regs->e.edi = buffer_adr;
 | 
			
		||||
	info = buffer;
 | 
			
		||||
	memset(info, '\0', sizeof(*info));
 | 
			
		||||
	strcpy(info->signature, "VBE2");
 | 
			
		||||
	BE_int86(0x10, regs, regs);
 | 
			
		||||
	if (regs->e.eax != 0x4f) {
 | 
			
		||||
		debug("VESA_GET_INFO: error %x\n", regs->e.eax);
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
	}
 | 
			
		||||
	debug("version %x\n", le16_to_cpu(info->version));
 | 
			
		||||
	debug("oem '%s'\n", (char *)bios_ptr(buffer, vga_info,
 | 
			
		||||
					     info->oem_string_ptr));
 | 
			
		||||
	debug("vendor '%s'\n", (char *)bios_ptr(buffer, vga_info,
 | 
			
		||||
						info->vendor_name_ptr));
 | 
			
		||||
	debug("product '%s'\n", (char *)bios_ptr(buffer, vga_info,
 | 
			
		||||
						 info->product_name_ptr));
 | 
			
		||||
	debug("rev '%s'\n", (char *)bios_ptr(buffer, vga_info,
 | 
			
		||||
					     info->product_rev_ptr));
 | 
			
		||||
	modes_bios = bios_ptr(buffer, vga_info, info->modes_ptr);
 | 
			
		||||
	debug("Modes: ");
 | 
			
		||||
	for (ptr = modes_bios; *ptr != 0xffff; ptr++)
 | 
			
		||||
		debug("%x ", le16_to_cpu(*ptr));
 | 
			
		||||
	debug("\nmemory %dMB\n", le16_to_cpu(info->total_memory) >> 4);
 | 
			
		||||
	size = (ptr - modes_bios) * sizeof(u16) + 2;
 | 
			
		||||
	modes = malloc(size);
 | 
			
		||||
	if (!modes)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	memcpy(modes, modes_bios, size);
 | 
			
		||||
 | 
			
		||||
	regs->e.eax = VESA_GET_CUR_MODE;
 | 
			
		||||
	BE_int86(0x10, regs, regs);
 | 
			
		||||
	if (regs->e.eax != 0x4f) {
 | 
			
		||||
		debug("VESA_GET_CUR_MODE: error %x\n", regs->e.eax);
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
	}
 | 
			
		||||
	debug("Current mode %x\n", regs->e.ebx);
 | 
			
		||||
 | 
			
		||||
	for (ptr = modes; *ptr != 0xffff; ptr++) {
 | 
			
		||||
		int mode = le16_to_cpu(*ptr);
 | 
			
		||||
		bool linear_ok;
 | 
			
		||||
		int attr;
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
		debug("Mode %x: ", mode);
 | 
			
		||||
		memset(buffer, '\0', sizeof(struct vbe_mode_info));
 | 
			
		||||
		regs->e.eax = VESA_GET_MODE_INFO;
 | 
			
		||||
		regs->e.ebx = 0;
 | 
			
		||||
		regs->e.ecx = mode;
 | 
			
		||||
		regs->e.edx = 0;
 | 
			
		||||
		regs->e.esi = buffer_seg;
 | 
			
		||||
		regs->e.edi = buffer_adr;
 | 
			
		||||
		BE_int86(0x10, regs, regs);
 | 
			
		||||
		if (regs->e.eax != 0x4f) {
 | 
			
		||||
			debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		memcpy(mode_info->mode_info_block, buffer,
 | 
			
		||||
		       sizeof(struct vesa_mode_info));
 | 
			
		||||
		mode_info->valid = true;
 | 
			
		||||
		vm = &mode_info->vesa;
 | 
			
		||||
		attr = le16_to_cpu(vm->mode_attributes);
 | 
			
		||||
		linear_ok = attr & 0x80;
 | 
			
		||||
		debug("res %d x %d, %d bpp, mm %d, (Linear %s, attr %02x)\n",
 | 
			
		||||
		      le16_to_cpu(vm->x_resolution),
 | 
			
		||||
		      le16_to_cpu(vm->y_resolution),
 | 
			
		||||
		      vm->bits_per_pixel, vm->memory_model,
 | 
			
		||||
		      linear_ok ? "OK" : "not available",
 | 
			
		||||
		      attr);
 | 
			
		||||
		debug("\tRGB pos=%d,%d,%d, size=%d,%d,%d\n",
 | 
			
		||||
		      vm->red_mask_pos, vm->green_mask_pos, vm->blue_mask_pos,
 | 
			
		||||
		      vm->red_mask_size, vm->green_mask_size,
 | 
			
		||||
		      vm->blue_mask_size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
 | 
			
		||||
				 struct vbe_mode_info *mode_info)
 | 
			
		||||
{
 | 
			
		||||
	void *buffer = (void *)(M.mem_base + vbe_offset);
 | 
			
		||||
	u16 buffer_seg = (((unsigned long)vbe_offset) >> 4) & 0xff00;
 | 
			
		||||
	u16 buffer_adr = ((unsigned long)vbe_offset) & 0xffff;
 | 
			
		||||
	struct vesa_mode_info *vm;
 | 
			
		||||
 | 
			
		||||
	debug("VBE: Setting VESA mode %#04x\n", vesa_mode);
 | 
			
		||||
	/* request linear framebuffer mode */
 | 
			
		||||
	vesa_mode |= (1 << 14);
 | 
			
		||||
	/* request clearing of framebuffer */
 | 
			
		||||
	vesa_mode &= ~(1 << 15);
 | 
			
		||||
	regs->e.eax = VESA_SET_MODE;
 | 
			
		||||
	regs->e.ebx = vesa_mode;
 | 
			
		||||
	/* request linear framebuffer mode and don't clear display */
 | 
			
		||||
	regs->e.ebx |= (1 << 14) | (1 << 15);
 | 
			
		||||
	BE_int86(0x10, regs, regs);
 | 
			
		||||
	if (regs->e.eax != 0x4f) {
 | 
			
		||||
		debug("VESA_SET_MODE: error %x\n", regs->e.eax);
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int offset = 0x2000;
 | 
			
		||||
	void *buffer = (void *)(M.mem_base + offset);
 | 
			
		||||
 | 
			
		||||
	u16 buffer_seg = (((unsigned long)offset) >> 4) & 0xff00;
 | 
			
		||||
	u16 buffer_adr = ((unsigned long)offset) & 0xffff;
 | 
			
		||||
	memset(buffer, '\0', sizeof(struct vbe_mode_info));
 | 
			
		||||
	debug("VBE: Geting info for VESA mode %#04x\n", vesa_mode);
 | 
			
		||||
	regs->e.eax = VESA_GET_MODE_INFO;
 | 
			
		||||
	regs->e.ebx = 0;
 | 
			
		||||
	regs->e.ecx = vesa_mode;
 | 
			
		||||
	regs->e.edx = 0;
 | 
			
		||||
	regs->e.esi = buffer_seg;
 | 
			
		||||
	regs->e.edi = buffer_adr;
 | 
			
		||||
	BE_int86(0x10, regs, regs);
 | 
			
		||||
	memcpy(mode_info->mode_info_block, buffer,
 | 
			
		||||
	       sizeof(struct vbe_mode_info));
 | 
			
		||||
	mode_info->valid = true;
 | 
			
		||||
	if (regs->e.eax != 0x4f) {
 | 
			
		||||
		debug("VESA_GET_MODE_INFO: error %x\n", regs->e.eax);
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vesa_mode |= (1 << 14);
 | 
			
		||||
	/* request clearing of framebuffer */
 | 
			
		||||
	vesa_mode &= ~(1 << 15);
 | 
			
		||||
	regs->e.eax = VESA_SET_MODE;
 | 
			
		||||
	regs->e.ebx = vesa_mode;
 | 
			
		||||
	BE_int86(0x10, regs, regs);
 | 
			
		||||
	memcpy(mode_info->mode_info_block, buffer,
 | 
			
		||||
		sizeof(struct vesa_mode_info));
 | 
			
		||||
	mode_info->valid = true;
 | 
			
		||||
	mode_info->video_mode = vesa_mode;
 | 
			
		||||
	vm = &mode_info->vesa;
 | 
			
		||||
	vm->x_resolution = le16_to_cpu(vm->x_resolution);
 | 
			
		||||
	vm->y_resolution = le16_to_cpu(vm->y_resolution);
 | 
			
		||||
	vm->bytes_per_scanline = le16_to_cpu(vm->bytes_per_scanline);
 | 
			
		||||
	vm->phys_base_ptr = le32_to_cpu(vm->phys_base_ptr);
 | 
			
		||||
	vm->mode_attributes = le16_to_cpu(vm->mode_attributes);
 | 
			
		||||
	debug("VBE: Init complete\n");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
@ -132,6 +250,9 @@ static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo *vga_info,
 | 
			
		||||
	/*Cleanup and exit*/
 | 
			
		||||
	BE_getVGA(vga_info);
 | 
			
		||||
 | 
			
		||||
	/* Useful for debugging */
 | 
			
		||||
	if (0)
 | 
			
		||||
		atibios_debug_mode(vga_info, ®s, vesa_mode, mode_info);
 | 
			
		||||
	if (vesa_mode != -1)
 | 
			
		||||
		atibios_set_vesa_mode(®s, vesa_mode, mode_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -102,7 +102,7 @@
 | 
			
		||||
# define ERR_PRINTF(x)		printf(x)
 | 
			
		||||
# define ERR_PRINTF2(x, y)	printf(x, y)
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_X86EMU_DEBUG103
 | 
			
		||||
#ifdef CONFIG_X86EMU_DEBUG
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# define DECODE_PRINTF(x)	if (DEBUG_DECODE()) \
 | 
			
		||||
 | 
			
		||||
@ -179,7 +179,7 @@ void x86emuOp_illegal_op(
 | 
			
		||||
{
 | 
			
		||||
    START_OF_INSTR();
 | 
			
		||||
    if (M.x86.R_SP != 0) {
 | 
			
		||||
	ERR_PRINTF("ILLEGAL X86 OPCODE\n");
 | 
			
		||||
	DB(printf("ILLEGAL X86 OPCODE\n"));
 | 
			
		||||
	TRACE_REGS();
 | 
			
		||||
	DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
 | 
			
		||||
	    M.x86.R_CS, M.x86.R_IP-1,op1));
 | 
			
		||||
 | 
			
		||||
@ -513,6 +513,20 @@ static void ahci_set_feature(u8 port)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int wait_spinup(volatile u8 *port_mmio)
 | 
			
		||||
{
 | 
			
		||||
	ulong start;
 | 
			
		||||
	u32 tf_data;
 | 
			
		||||
 | 
			
		||||
	start = get_timer(0);
 | 
			
		||||
	do {
 | 
			
		||||
		tf_data = readl(port_mmio + PORT_TFDATA);
 | 
			
		||||
		if (!(tf_data & ATA_BUSY))
 | 
			
		||||
			return 0;
 | 
			
		||||
	} while (get_timer(start) < WAIT_MS_SPINUP);
 | 
			
		||||
 | 
			
		||||
	return -ETIMEDOUT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ahci_port_start(u8 port)
 | 
			
		||||
{
 | 
			
		||||
@ -579,7 +593,11 @@ static int ahci_port_start(u8 port)
 | 
			
		||||
 | 
			
		||||
	debug("Exit start port %d\n", port);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
	/*
 | 
			
		||||
	 * Make sure interface is not busy based on error and status
 | 
			
		||||
	 * information from task file data register before proceeding
 | 
			
		||||
	 */
 | 
			
		||||
	return wait_spinup(port_mmio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <pci.h>
 | 
			
		||||
 | 
			
		||||
#undef DEBUG
 | 
			
		||||
@ -191,6 +191,32 @@ void pciauto_setup_device(struct pci_controller *hose,
 | 
			
		||||
	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	pci_addr_t bar_value;
 | 
			
		||||
	pci_size_t bar_size;
 | 
			
		||||
	u32 bar_response;
 | 
			
		||||
	u16 cmdstat = 0;
 | 
			
		||||
 | 
			
		||||
	pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe);
 | 
			
		||||
	pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response);
 | 
			
		||||
	if (!bar_response)
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
 | 
			
		||||
	bar_size = -(bar_response & ~1);
 | 
			
		||||
	DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
 | 
			
		||||
	if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) {
 | 
			
		||||
		pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS,
 | 
			
		||||
					    bar_value);
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGF("\n");
 | 
			
		||||
	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
 | 
			
		||||
	cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 | 
			
		||||
	pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 | 
			
		||||
					 pci_dev_t dev, int sub_bus)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -66,6 +66,7 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
 | 
			
		||||
	struct pci_rom_header *rom_header;
 | 
			
		||||
	struct pci_rom_data *rom_data;
 | 
			
		||||
	u16 vendor, device;
 | 
			
		||||
	u16 rom_vendor, rom_device;
 | 
			
		||||
	u32 vendev;
 | 
			
		||||
	u32 mapped_vendev;
 | 
			
		||||
	u32 rom_address;
 | 
			
		||||
@ -80,7 +81,12 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
 | 
			
		||||
#ifdef CONFIG_X86_OPTION_ROM_ADDR
 | 
			
		||||
	rom_address = CONFIG_X86_OPTION_ROM_ADDR;
 | 
			
		||||
#else
 | 
			
		||||
	pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
 | 
			
		||||
 | 
			
		||||
	if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) {
 | 
			
		||||
		debug("Cannot find option ROM\n");
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address);
 | 
			
		||||
	if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
 | 
			
		||||
		debug("%s: rom_address=%x\n", __func__, rom_address);
 | 
			
		||||
@ -95,26 +101,28 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
 | 
			
		||||
	rom_header = (struct pci_rom_header *)rom_address;
 | 
			
		||||
 | 
			
		||||
	debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n",
 | 
			
		||||
	      le32_to_cpu(rom_header->signature),
 | 
			
		||||
	      rom_header->size * 512, le32_to_cpu(rom_header->data));
 | 
			
		||||
	      le16_to_cpu(rom_header->signature),
 | 
			
		||||
	      rom_header->size * 512, le16_to_cpu(rom_header->data));
 | 
			
		||||
 | 
			
		||||
	if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
 | 
			
		||||
	if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
 | 
			
		||||
		printf("Incorrect expansion ROM header signature %04x\n",
 | 
			
		||||
		       le32_to_cpu(rom_header->signature));
 | 
			
		||||
		       le16_to_cpu(rom_header->signature));
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
 | 
			
		||||
	rom_data = (((void *)rom_header) + le16_to_cpu(rom_header->data));
 | 
			
		||||
	rom_vendor = le16_to_cpu(rom_data->vendor);
 | 
			
		||||
	rom_device = le16_to_cpu(rom_data->device);
 | 
			
		||||
 | 
			
		||||
	debug("PCI ROM image, vendor ID %04x, device ID %04x,\n",
 | 
			
		||||
	      rom_data->vendor, rom_data->device);
 | 
			
		||||
	      rom_vendor, rom_device);
 | 
			
		||||
 | 
			
		||||
	/* If the device id is mapped, a mismatch is expected */
 | 
			
		||||
	if ((vendor != rom_data->vendor || device != rom_data->device) &&
 | 
			
		||||
	if ((vendor != rom_vendor || device != rom_device) &&
 | 
			
		||||
	    (vendev == mapped_vendev)) {
 | 
			
		||||
		printf("ID mismatch: vendor ID %04x, device ID %04x\n",
 | 
			
		||||
		       rom_data->vendor, rom_data->device);
 | 
			
		||||
		return -EPERM;
 | 
			
		||||
		       rom_vendor, rom_device);
 | 
			
		||||
		/* Continue anyway */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	debug("PCI ROM image, Class Code %04x%02x, Code Type %02x\n",
 | 
			
		||||
@ -144,17 +152,23 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header,
 | 
			
		||||
							    image_size);
 | 
			
		||||
 | 
			
		||||
		rom_data = (struct pci_rom_data *)((void *)rom_header +
 | 
			
		||||
				le32_to_cpu(rom_header->data));
 | 
			
		||||
				le16_to_cpu(rom_header->data));
 | 
			
		||||
 | 
			
		||||
		image_size = le32_to_cpu(rom_data->ilen) * 512;
 | 
			
		||||
	} while ((rom_data->type != 0) && (rom_data->indicator != 0));
 | 
			
		||||
		image_size = le16_to_cpu(rom_data->ilen) * 512;
 | 
			
		||||
	} while ((rom_data->type != 0) && (rom_data->indicator == 0));
 | 
			
		||||
 | 
			
		||||
	if (rom_data->type != 0)
 | 
			
		||||
		return -EACCES;
 | 
			
		||||
 | 
			
		||||
	rom_size = rom_header->size * 512;
 | 
			
		||||
 | 
			
		||||
#ifdef PCI_VGA_RAM_IMAGE_START
 | 
			
		||||
	target = (void *)PCI_VGA_RAM_IMAGE_START;
 | 
			
		||||
#else
 | 
			
		||||
	target = (void *)malloc(rom_size);
 | 
			
		||||
	if (!target)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
#endif
 | 
			
		||||
	if (target != rom_header) {
 | 
			
		||||
		ulong start = get_timer(0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -459,7 +459,6 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
 | 
			
		||||
				      unsigned int *lanes)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_pci_addr addr;
 | 
			
		||||
	pci_dev_t bdf;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0);
 | 
			
		||||
@ -470,13 +469,13 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
 | 
			
		||||
 | 
			
		||||
	*lanes = err;
 | 
			
		||||
 | 
			
		||||
	err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf);
 | 
			
		||||
	err = fdtdec_get_pci_addr(fdt, node, 0, "reg", &addr);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		error("failed to parse \"reg\" property");
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*index = PCI_DEV(bdf) - 1;
 | 
			
		||||
	*index = PCI_DEV(addr.phys_hi) - 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,9 +27,6 @@
 | 
			
		||||
/* Set this to 1 to clear the CMOS RAM */
 | 
			
		||||
#define CLEAR_CMOS 0
 | 
			
		||||
 | 
			
		||||
static uchar rtc_read  (uchar reg);
 | 
			
		||||
static void  rtc_write (uchar reg, uchar val);
 | 
			
		||||
 | 
			
		||||
#define RTC_PORT_MC146818	CONFIG_SYS_ISA_IO_BASE_ADDRESS +  0x70
 | 
			
		||||
#define RTC_SECONDS		0x00
 | 
			
		||||
#define RTC_SECONDS_ALARM	0x01
 | 
			
		||||
@ -60,24 +57,24 @@ int rtc_get (struct rtc_time *tmp)
 | 
			
		||||
{
 | 
			
		||||
	uchar sec, min, hour, mday, wday, mon, year;
 | 
			
		||||
  /* here check if rtc can be accessed */
 | 
			
		||||
	while((rtc_read(RTC_CONFIG_A)&0x80)==0x80);
 | 
			
		||||
	sec	= rtc_read (RTC_SECONDS);
 | 
			
		||||
	min	= rtc_read (RTC_MINUTES);
 | 
			
		||||
	hour	= rtc_read (RTC_HOURS);
 | 
			
		||||
	mday	= rtc_read (RTC_DATE_OF_MONTH);
 | 
			
		||||
	wday	= rtc_read (RTC_DAY_OF_WEEK);
 | 
			
		||||
	mon	= rtc_read (RTC_MONTH);
 | 
			
		||||
	year	= rtc_read (RTC_YEAR);
 | 
			
		||||
	while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80);
 | 
			
		||||
	sec	= rtc_read8(RTC_SECONDS);
 | 
			
		||||
	min	= rtc_read8(RTC_MINUTES);
 | 
			
		||||
	hour	= rtc_read8(RTC_HOURS);
 | 
			
		||||
	mday	= rtc_read8(RTC_DATE_OF_MONTH);
 | 
			
		||||
	wday	= rtc_read8(RTC_DAY_OF_WEEK);
 | 
			
		||||
	mon	= rtc_read8(RTC_MONTH);
 | 
			
		||||
	year	= rtc_read8(RTC_YEAR);
 | 
			
		||||
#ifdef RTC_DEBUG
 | 
			
		||||
	printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
 | 
			
		||||
		"hr: %02x min: %02x sec: %02x\n",
 | 
			
		||||
		year, mon, mday, wday,
 | 
			
		||||
		hour, min, sec );
 | 
			
		||||
	printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
 | 
			
		||||
		rtc_read (RTC_CONFIG_D) & 0x3F,
 | 
			
		||||
		rtc_read (RTC_HOURS_ALARM),
 | 
			
		||||
		rtc_read (RTC_MINUTES_ALARM),
 | 
			
		||||
		rtc_read (RTC_SECONDS_ALARM) );
 | 
			
		||||
		rtc_read8(RTC_CONFIG_D) & 0x3F,
 | 
			
		||||
		rtc_read8(RTC_HOURS_ALARM),
 | 
			
		||||
		rtc_read8(RTC_MINUTES_ALARM),
 | 
			
		||||
		rtc_read8(RTC_SECONDS_ALARM));
 | 
			
		||||
#endif
 | 
			
		||||
	tmp->tm_sec  = bcd2bin (sec  & 0x7F);
 | 
			
		||||
	tmp->tm_min  = bcd2bin (min  & 0x7F);
 | 
			
		||||
@ -108,80 +105,108 @@ int rtc_set (struct rtc_time *tmp)
 | 
			
		||||
		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 | 
			
		||||
		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 | 
			
		||||
#endif
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
 | 
			
		||||
 | 
			
		||||
	rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
 | 
			
		||||
	rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
 | 
			
		||||
	rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
 | 
			
		||||
	rtc_write (RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
 | 
			
		||||
	rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
 | 
			
		||||
	rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
 | 
			
		||||
	rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
 | 
			
		||||
	rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
 | 
			
		||||
	rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
 | 
			
		||||
	rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
 | 
			
		||||
	rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
 | 
			
		||||
	rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
 | 
			
		||||
	rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
 | 
			
		||||
	rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_reset (void)
 | 
			
		||||
{
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
 | 
			
		||||
	rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x00);
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x00);
 | 
			
		||||
	rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
 | 
			
		||||
	rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x00);
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x00);
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 | 
			
		||||
/*
 | 
			
		||||
 * use direct memory access
 | 
			
		||||
 */
 | 
			
		||||
static uchar rtc_read (uchar reg)
 | 
			
		||||
int rtc_read8(int reg)
 | 
			
		||||
{
 | 
			
		||||
#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 | 
			
		||||
	return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rtc_write (uchar reg, uchar val)
 | 
			
		||||
{
 | 
			
		||||
	out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static uchar rtc_read (uchar reg)
 | 
			
		||||
{
 | 
			
		||||
	out8(RTC_PORT_MC146818,reg);
 | 
			
		||||
	return in8(RTC_PORT_MC146818 + 1);
 | 
			
		||||
	int ofs = 0;
 | 
			
		||||
 | 
			
		||||
	if (reg >= 128) {
 | 
			
		||||
		ofs = 2;
 | 
			
		||||
		reg -= 128;
 | 
			
		||||
	}
 | 
			
		||||
	out8(RTC_PORT_MC146818 + ofs, reg);
 | 
			
		||||
 | 
			
		||||
	return in8(RTC_PORT_MC146818 + ofs + 1);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rtc_write (uchar reg, uchar val)
 | 
			
		||||
void rtc_write8(int reg, uchar val)
 | 
			
		||||
{
 | 
			
		||||
	out8(RTC_PORT_MC146818,reg);
 | 
			
		||||
	out8(RTC_PORT_MC146818+1, val);
 | 
			
		||||
}
 | 
			
		||||
#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 | 
			
		||||
	out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
 | 
			
		||||
#else
 | 
			
		||||
	int ofs = 0;
 | 
			
		||||
 | 
			
		||||
	if (reg >= 128) {
 | 
			
		||||
		ofs = 2;
 | 
			
		||||
		reg -= 128;
 | 
			
		||||
	}
 | 
			
		||||
	out8(RTC_PORT_MC146818 + ofs, reg);
 | 
			
		||||
	out8(RTC_PORT_MC146818 + ofs + 1, val);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 rtc_read32(int reg)
 | 
			
		||||
{
 | 
			
		||||
	u32 value = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sizeof(value); i++)
 | 
			
		||||
		value |= rtc_read8(reg + i) << (i << 3);
 | 
			
		||||
 | 
			
		||||
	return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_write32(int reg, u32 value)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sizeof(value); i++)
 | 
			
		||||
		rtc_write8(reg + i, (value >> (i << 3)) & 0xff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rtc_init(void)
 | 
			
		||||
{
 | 
			
		||||
#if CLEAR_CMOS
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	rtc_write(RTC_SECONDS_ALARM, 0);
 | 
			
		||||
	rtc_write(RTC_MINUTES_ALARM, 0);
 | 
			
		||||
	rtc_write(RTC_HOURS_ALARM, 0);
 | 
			
		||||
	rtc_write8(RTC_SECONDS_ALARM, 0);
 | 
			
		||||
	rtc_write8(RTC_MINUTES_ALARM, 0);
 | 
			
		||||
	rtc_write8(RTC_HOURS_ALARM, 0);
 | 
			
		||||
	for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
 | 
			
		||||
		rtc_write(i, 0);
 | 
			
		||||
		rtc_write8(i, 0);
 | 
			
		||||
	printf("RTC: zeroing CMOS RAM\n");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Setup the real time clock */
 | 
			
		||||
	rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H);
 | 
			
		||||
	rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
 | 
			
		||||
	/* Setup the frequency it operates at */
 | 
			
		||||
	rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
 | 
			
		||||
	rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
 | 
			
		||||
		  RTC_CONFIG_A_RATE_1024HZ);
 | 
			
		||||
	/* Ensure all reserved bits are 0 in register D */
 | 
			
		||||
	rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
 | 
			
		||||
	rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
 | 
			
		||||
 | 
			
		||||
	/* Clear any pending interrupts */
 | 
			
		||||
	rtc_read(RTC_CONFIG_C);
 | 
			
		||||
	rtc_read8(RTC_CONFIG_C);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -153,6 +153,13 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 | 
			
		||||
	return &ich->slave;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
 | 
			
		||||
				      int spi_node)
 | 
			
		||||
{
 | 
			
		||||
	/* We only support a single SPI at present */
 | 
			
		||||
	return spi_setup_slave(0, 0, 20000000, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void spi_free_slave(struct spi_slave *slave)
 | 
			
		||||
{
 | 
			
		||||
	struct ich_spi_slave *ich = to_ich_spi(slave);
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
config VIDEO_X86
 | 
			
		||||
	bool "Enable x86 video driver support"
 | 
			
		||||
config VIDEO_VESA
 | 
			
		||||
	bool "Enable VESA video driver support"
 | 
			
		||||
	depends on X86
 | 
			
		||||
	default n
 | 
			
		||||
	help
 | 
			
		||||
	  Turn on this option to enable a very simple driver which uses vesa
 | 
			
		||||
	  to discover the video mode and then provides a frame buffer for use
 | 
			
		||||
	  by U-Boot.
 | 
			
		||||
	  by U-Boot. This can in principle be used with any platform that
 | 
			
		||||
	  supports PCI and video cards that support VESA BIOS Extension (VBE).
 | 
			
		||||
 | 
			
		||||
config VIDEO_LCD_SSD2828
 | 
			
		||||
	bool "SSD2828 bridge chip"
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o videomodes.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_X86) += x86_fb.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o
 | 
			
		||||
obj-$(CONFIG_FORMIKE) += formike.o
 | 
			
		||||
obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 | 
			
		||||
obj-$(CONFIG_VIDEO_PARADE) += parade.o
 | 
			
		||||
 | 
			
		||||
@ -299,7 +299,11 @@ void console_cursor(int state);
 | 
			
		||||
#define CONSOLE_ROW_SECOND	(video_console_address + CONSOLE_ROW_SIZE)
 | 
			
		||||
#define CONSOLE_ROW_LAST	(video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
 | 
			
		||||
#define CONSOLE_SIZE		(CONSOLE_ROW_SIZE * CONSOLE_ROWS)
 | 
			
		||||
#define CONSOLE_SCROLL_SIZE	(CONSOLE_SIZE - CONSOLE_ROW_SIZE)
 | 
			
		||||
 | 
			
		||||
/* By default we scroll by a single line */
 | 
			
		||||
#ifndef CONFIG_CONSOLE_SCROLL_LINES
 | 
			
		||||
#define CONFIG_CONSOLE_SCROLL_LINES 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Macros */
 | 
			
		||||
#ifdef	VIDEO_FB_LITTLE_ENDIAN
 | 
			
		||||
@ -740,26 +744,33 @@ static void console_clear_line(int line, int begin, int end)
 | 
			
		||||
 | 
			
		||||
static void console_scrollup(void)
 | 
			
		||||
{
 | 
			
		||||
	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* copy up rows ignoring the first one */
 | 
			
		||||
 | 
			
		||||
#ifdef VIDEO_HW_BITBLT
 | 
			
		||||
	video_hw_bitblt(VIDEO_PIXEL_SIZE,	/* bytes per pixel */
 | 
			
		||||
			0,			/* source pos x */
 | 
			
		||||
			video_logo_height +
 | 
			
		||||
				VIDEO_FONT_HEIGHT, /* source pos y */
 | 
			
		||||
				VIDEO_FONT_HEIGHT * rows, /* source pos y */
 | 
			
		||||
			0,			/* dest pos x */
 | 
			
		||||
			video_logo_height,	/* dest pos y */
 | 
			
		||||
			VIDEO_VISIBLE_COLS,	/* frame width */
 | 
			
		||||
			VIDEO_VISIBLE_ROWS
 | 
			
		||||
			- video_logo_height
 | 
			
		||||
			- VIDEO_FONT_HEIGHT	/* frame height */
 | 
			
		||||
			- VIDEO_FONT_HEIGHT * rows	/* frame height */
 | 
			
		||||
		);
 | 
			
		||||
#else
 | 
			
		||||
	memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
 | 
			
		||||
		CONSOLE_SCROLL_SIZE >> 2);
 | 
			
		||||
	memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_FIRST + rows * CONSOLE_ROW_SIZE,
 | 
			
		||||
		(CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows) >> 2);
 | 
			
		||||
#endif
 | 
			
		||||
	/* clear the last one */
 | 
			
		||||
	console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
 | 
			
		||||
	for (i = 1; i <= rows; i++)
 | 
			
		||||
		console_clear_line(CONSOLE_ROWS - i, 0, CONSOLE_COLS - 1);
 | 
			
		||||
 | 
			
		||||
	/* Decrement row number */
 | 
			
		||||
	console_row -= rows;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void console_back(void)
 | 
			
		||||
@ -871,9 +882,6 @@ static void console_newline(int n)
 | 
			
		||||
	if (console_row >= CONSOLE_ROWS) {
 | 
			
		||||
		/* Scroll everything up */
 | 
			
		||||
		console_scrollup();
 | 
			
		||||
 | 
			
		||||
		/* Decrement row number */
 | 
			
		||||
		console_row = CONSOLE_ROWS - 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								drivers/video/vesa_fb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								drivers/video/vesa_fb.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Vesa frame buffer driver for x86
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2014 Google, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier:	GPL-2.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <pci_rom.h>
 | 
			
		||||
#include <video_fb.h>
 | 
			
		||||
#include <vbe.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The Graphic Device
 | 
			
		||||
 */
 | 
			
		||||
GraphicDevice ctfb;
 | 
			
		||||
 | 
			
		||||
/* Devices to allow - only the last one works fully */
 | 
			
		||||
struct pci_device_id vesa_video_ids[] = {
 | 
			
		||||
	{ .vendor = 0x102b, .device = 0x0525 },
 | 
			
		||||
	{ .vendor = 0x1002, .device = 0x5159 },
 | 
			
		||||
	{ .vendor = 0x1002, .device = 0x4752 },
 | 
			
		||||
	{ .vendor = 0x1002, .device = 0x5452 },
 | 
			
		||||
	{},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void *video_hw_init(void)
 | 
			
		||||
{
 | 
			
		||||
	GraphicDevice *gdev = &ctfb;
 | 
			
		||||
	int bits_per_pixel;
 | 
			
		||||
	pci_dev_t dev;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	printf("Video: ");
 | 
			
		||||
	if (vbe_get_video_info(gdev)) {
 | 
			
		||||
		/* TODO: Should we look these up by class? */
 | 
			
		||||
		dev = pci_find_devices(vesa_video_ids, 0);
 | 
			
		||||
		if (dev == -1) {
 | 
			
		||||
			printf("no card detected\n");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		printf("bdf %x\n", dev);
 | 
			
		||||
		ret = pci_run_vga_bios(dev, NULL, true);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			printf("failed to run video BIOS: %d\n", ret);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (vbe_get_video_info(gdev)) {
 | 
			
		||||
		printf("No video mode configured\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bits_per_pixel = gdev->gdfBytesPP * 8;
 | 
			
		||||
	sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
 | 
			
		||||
		bits_per_pixel);
 | 
			
		||||
	printf("%s\n", gdev->modeIdent);
 | 
			
		||||
	debug("Framex buffer at %x\n", gdev->pciBase);
 | 
			
		||||
 | 
			
		||||
	return (void *)gdev;
 | 
			
		||||
}
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Vesa frame buffer driver for x86
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2014 Google, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier:	GPL-2.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <video_fb.h>
 | 
			
		||||
#include <vbe.h>
 | 
			
		||||
#include "videomodes.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The Graphic Device
 | 
			
		||||
 */
 | 
			
		||||
GraphicDevice ctfb;
 | 
			
		||||
 | 
			
		||||
void *video_hw_init(void)
 | 
			
		||||
{
 | 
			
		||||
	GraphicDevice *gdev = &ctfb;
 | 
			
		||||
	int bits_per_pixel;
 | 
			
		||||
 | 
			
		||||
	printf("Video: ");
 | 
			
		||||
	if (vbe_get_video_info(gdev)) {
 | 
			
		||||
		printf("No video mode configured\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bits_per_pixel = gdev->gdfBytesPP * 8;
 | 
			
		||||
	sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
 | 
			
		||||
		bits_per_pixel);
 | 
			
		||||
	printf("%s\n", gdev->modeIdent);
 | 
			
		||||
	debug("Frame buffer at %x\n", gdev->frameAdrs);
 | 
			
		||||
 | 
			
		||||
	return (void *)gdev;
 | 
			
		||||
}
 | 
			
		||||
@ -20,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE		0x4000
 | 
			
		||||
#define CONFIG_BOARD_EARLY_INIT_F
 | 
			
		||||
#define CONFIG_MISC_INIT_R
 | 
			
		||||
 | 
			
		||||
#define CONFIG_NR_DRAM_BANKS			8
 | 
			
		||||
#define CONFIG_X86_MRC_ADDR			0xfffa0000
 | 
			
		||||
@ -63,6 +64,13 @@
 | 
			
		||||
#define CONFIG_CMD_CROS_EC
 | 
			
		||||
#define CONFIG_ARCH_EARLY_INIT_R
 | 
			
		||||
 | 
			
		||||
#undef CONFIG_ENV_IS_NOWHERE
 | 
			
		||||
#undef CONFIG_ENV_SIZE
 | 
			
		||||
#define CONFIG_ENV_SIZE			0x1000
 | 
			
		||||
#define CONFIG_ENV_SECT_SIZE		0x1000
 | 
			
		||||
#define CONFIG_ENV_IS_IN_SPI_FLASH
 | 
			
		||||
#define CONFIG_ENV_OFFSET		0x003f8000
 | 
			
		||||
 | 
			
		||||
#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
 | 
			
		||||
					"stdout=vga,serial\0" \
 | 
			
		||||
					"stderr=vga,serial\0"
 | 
			
		||||
 | 
			
		||||
@ -179,6 +179,7 @@
 | 
			
		||||
#define VIDEO_FB_16BPP_WORD_SWAP
 | 
			
		||||
#define CONFIG_I8042_KBD
 | 
			
		||||
#define CONFIG_CFB_CONSOLE
 | 
			
		||||
#define CONFIG_CONSOLE_SCROLL_LINES 5
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------
 | 
			
		||||
 * CPU Features
 | 
			
		||||
@ -210,6 +211,7 @@
 | 
			
		||||
#define CONFIG_CMD_SF_TEST
 | 
			
		||||
#define CONFIG_CMD_SPI
 | 
			
		||||
#define CONFIG_SPI
 | 
			
		||||
#define CONFIG_OF_SPI_FLASH
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------------
 | 
			
		||||
 * Environment configuration
 | 
			
		||||
 | 
			
		||||
@ -173,6 +173,7 @@ enum fdt_compat_id {
 | 
			
		||||
	COMPAT_INTEL_MODEL_206AX,	/* Intel Model 206AX CPU */
 | 
			
		||||
	COMPAT_INTEL_GMA,		/* Intel Graphics Media Accelerator */
 | 
			
		||||
	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 | 
			
		||||
	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 | 
			
		||||
 | 
			
		||||
	COMPAT_COUNT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -482,6 +482,36 @@ extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
 | 
			
		||||
extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 | 
			
		||||
				int sport, int len);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * compute_ip_checksum() - Compute IP checksum
 | 
			
		||||
 *
 | 
			
		||||
 * @addr:	Address to check (must be 16-bit aligned)
 | 
			
		||||
 * @nbytes:	Number of bytes to check (normally a multiple of 2)
 | 
			
		||||
 * @return 16-bit IP checksum
 | 
			
		||||
 */
 | 
			
		||||
unsigned compute_ip_checksum(const void *addr, unsigned nbytes);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * add_ip_checksums() - add two IP checksums
 | 
			
		||||
 *
 | 
			
		||||
 * @offset:	Offset of first sum (if odd we do a byte-swap)
 | 
			
		||||
 * @sum:	First checksum
 | 
			
		||||
 * @new_sum:	New checksum to add
 | 
			
		||||
 * @return updated 16-bit IP checksum
 | 
			
		||||
 */
 | 
			
		||||
unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ip_checksum_ok() - check if a checksum is correct
 | 
			
		||||
 *
 | 
			
		||||
 * This works by making sure the checksum sums to 0
 | 
			
		||||
 *
 | 
			
		||||
 * @addr:	Address to check (must be 16-bit aligned)
 | 
			
		||||
 * @nbytes:	Number of bytes to check (normally a multiple of 2)
 | 
			
		||||
 * @return true if the checksum matches, false if not
 | 
			
		||||
 */
 | 
			
		||||
int ip_checksum_ok(const void *addr, unsigned nbytes);
 | 
			
		||||
 | 
			
		||||
/* Checksum */
 | 
			
		||||
extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
 | 
			
		||||
extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
 | 
			
		||||
 | 
			
		||||
@ -697,5 +697,14 @@ void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
 | 
			
		||||
 * */
 | 
			
		||||
u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pciauto_setup_rom() - Set up access to a device ROM
 | 
			
		||||
 *
 | 
			
		||||
 * @hose:	PCI hose to use
 | 
			
		||||
 * @dev:	PCI device to adjust
 | 
			
		||||
 * @return 0 if done, -ve on error
 | 
			
		||||
 */
 | 
			
		||||
int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev);
 | 
			
		||||
 | 
			
		||||
#endif /* __ASSEMBLY__ */
 | 
			
		||||
#endif /* _PCI_H */
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,6 @@
 | 
			
		||||
#define _PCI_ROM_H
 | 
			
		||||
 | 
			
		||||
#define PCI_ROM_HDR			0xaa55
 | 
			
		||||
#define PCI_VGA_RAM_IMAGE_START		0xc0000
 | 
			
		||||
 | 
			
		||||
struct pci_rom_header {
 | 
			
		||||
	uint16_t signature;
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,38 @@ void to_tm (int, struct rtc_time *);
 | 
			
		||||
unsigned long mktime (unsigned int, unsigned int, unsigned int,
 | 
			
		||||
		      unsigned int, unsigned int, unsigned int);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rtc_read8() - Read an 8-bit register
 | 
			
		||||
 *
 | 
			
		||||
 * @reg:	Register to read
 | 
			
		||||
 * @return value read
 | 
			
		||||
 */
 | 
			
		||||
int rtc_read8(int reg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rtc_write8() - Write an 8-bit register
 | 
			
		||||
 *
 | 
			
		||||
 * @reg:	Register to write
 | 
			
		||||
 * @value:	Value to write
 | 
			
		||||
 */
 | 
			
		||||
void rtc_write8(int reg, uchar val);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rtc_read32() - Read a 32-bit value from the RTC
 | 
			
		||||
 *
 | 
			
		||||
 * @reg:	Offset to start reading from
 | 
			
		||||
 * @return value read
 | 
			
		||||
 */
 | 
			
		||||
u32 rtc_read32(int reg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rtc_write32() - Write a 32-bit value to the RTC
 | 
			
		||||
 *
 | 
			
		||||
 * @reg:	Register to start writing to
 | 
			
		||||
 * @value:	Value to write
 | 
			
		||||
 */
 | 
			
		||||
void rtc_write32(int reg, u32 value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rtc_init() - Set up the real time clock ready for use
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,14 @@ struct __packed screen_info_input {
 | 
			
		||||
struct __packed vbe_info {
 | 
			
		||||
	char signature[4];
 | 
			
		||||
	u16 version;
 | 
			
		||||
	u8 *oem_string_ptr;
 | 
			
		||||
	u32 oem_string_ptr;
 | 
			
		||||
	u32 capabilities;
 | 
			
		||||
	u16 video_mode_list[256];
 | 
			
		||||
	u32 modes_ptr;
 | 
			
		||||
	u16 total_memory;
 | 
			
		||||
	u16 oem_version;
 | 
			
		||||
	u32 vendor_name_ptr;
 | 
			
		||||
	u32 product_name_ptr;
 | 
			
		||||
	u32 product_rev_ptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct __packed vesa_mode_info {
 | 
			
		||||
@ -96,6 +100,7 @@ struct vbe_ddc_info {
 | 
			
		||||
#define VESA_GET_INFO		0x4f00
 | 
			
		||||
#define VESA_GET_MODE_INFO	0x4f01
 | 
			
		||||
#define VESA_SET_MODE		0x4f02
 | 
			
		||||
#define VESA_GET_CUR_MODE	0x4f03
 | 
			
		||||
 | 
			
		||||
struct graphic_device;
 | 
			
		||||
int vbe_get_video_info(struct graphic_device *gdev);
 | 
			
		||||
 | 
			
		||||
@ -83,6 +83,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 | 
			
		||||
	COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
 | 
			
		||||
	COMPAT(INTEL_GMA, "intel,gma"),
 | 
			
		||||
	COMPAT(AMS_AS3722, "ams,as3722"),
 | 
			
		||||
	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *fdtdec_get_compatible(enum fdt_compat_id id)
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#ccflags-y += -DDEBUG
 | 
			
		||||
 | 
			
		||||
obj-y += checksum.o
 | 
			
		||||
obj-$(CONFIG_CMD_NET)  += arp.o
 | 
			
		||||
obj-$(CONFIG_CMD_NET)  += bootp.o
 | 
			
		||||
obj-$(CONFIG_CMD_CDP)  += cdp.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								net/checksum.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								net/checksum.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file was originally taken from the FreeBSD project.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
 | 
			
		||||
 * Copyright (c) 2008 coresystems GmbH
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier:	BSD-2-Clause
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <net.h>
 | 
			
		||||
 | 
			
		||||
unsigned compute_ip_checksum(const void *vptr, unsigned nbytes)
 | 
			
		||||
{
 | 
			
		||||
	int sum, oddbyte;
 | 
			
		||||
	const unsigned short *ptr = vptr;
 | 
			
		||||
 | 
			
		||||
	sum = 0;
 | 
			
		||||
	while (nbytes > 1) {
 | 
			
		||||
		sum += *ptr++;
 | 
			
		||||
		nbytes -= 2;
 | 
			
		||||
	}
 | 
			
		||||
	if (nbytes == 1) {
 | 
			
		||||
		oddbyte = 0;
 | 
			
		||||
		((u8 *)&oddbyte)[0] = *(u8 *)ptr;
 | 
			
		||||
		((u8 *)&oddbyte)[1] = 0;
 | 
			
		||||
		sum += oddbyte;
 | 
			
		||||
	}
 | 
			
		||||
	sum = (sum >> 16) + (sum & 0xffff);
 | 
			
		||||
	sum += (sum >> 16);
 | 
			
		||||
	sum = ~sum & 0xffff;
 | 
			
		||||
 | 
			
		||||
	return sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long checksum;
 | 
			
		||||
 | 
			
		||||
	sum = ~sum & 0xffff;
 | 
			
		||||
	new = ~new & 0xffff;
 | 
			
		||||
	if (offset & 1) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * byte-swap the sum if it came from an odd offset; since the
 | 
			
		||||
		 * computation is endian independant this works.
 | 
			
		||||
		 */
 | 
			
		||||
		new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
 | 
			
		||||
	}
 | 
			
		||||
	checksum = sum + new;
 | 
			
		||||
	if (checksum > 0xffff)
 | 
			
		||||
		checksum -= 0xffff;
 | 
			
		||||
 | 
			
		||||
	return (~checksum) & 0xffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ip_checksum_ok(const void *addr, unsigned nbytes)
 | 
			
		||||
{
 | 
			
		||||
	return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user