diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/avr32/cpu/at32ap700x/mmu.c | 2 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/Makefile | 58 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/asm-offsets.c | 25 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/coreboot_car.S | 29 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/ipchecksum.c | 54 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/sdram.c | 75 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/sysinfo.c | 39 | ||||
| -rw-r--r-- | arch/x86/cpu/coreboot/tables.c | 183 | ||||
| -rw-r--r-- | arch/x86/include/asm/arch-coreboot/ipchecksum.h | 37 | ||||
| -rw-r--r-- | arch/x86/include/asm/arch-coreboot/sysinfo.h | 63 | ||||
| -rw-r--r-- | arch/x86/include/asm/arch-coreboot/tables.h | 241 | ||||
| -rw-r--r-- | arch/x86/include/asm/zimage.h | 36 | ||||
| -rw-r--r-- | arch/x86/lib/bootm.c | 21 | ||||
| -rw-r--r-- | arch/x86/lib/zimage.c | 276 | 
14 files changed, 1011 insertions, 128 deletions
| diff --git a/arch/avr32/cpu/at32ap700x/mmu.c b/arch/avr32/cpu/at32ap700x/mmu.c index c3a1b9367..0e28b21ee 100644 --- a/arch/avr32/cpu/at32ap700x/mmu.c +++ b/arch/avr32/cpu/at32ap700x/mmu.c @@ -22,7 +22,7 @@ void mmu_init_r(unsigned long dest_addr)  	 */  	vmr_table_addr = (uintptr_t)&mmu_vmr_table;  	sysreg_write(PTBR, vmr_table_addr); -	printf("VMR table @ 0x%08x\n", vmr_table_addr); +	printf("VMR table @ 0x%08lx\n", vmr_table_addr);  	/* Enable paging */  	sysreg_write(MMUCR, SYSREG_BF(DRP, 1) | SYSREG_BF(DLA, 1) diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile new file mode 100644 index 000000000..13f5f8a2f --- /dev/null +++ b/arch/x86/cpu/coreboot/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (c) 2011 The Chromium OS Authors. +# +# (C) Copyright 2008 +# Graeme Russ, graeme.russ@gmail.com. +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	:= $(obj)lib$(SOC).o + +COBJS-$(CONFIG_SYS_COREBOOT) += tables.o +COBJS-$(CONFIG_SYS_COREBOOT) += ipchecksum.o +COBJS-$(CONFIG_SYS_COREBOOT) += sdram.o +COBJS-$(CONFIG_SYS_COREBOOT) += sysinfo.o + +SOBJS-$(CONFIG_SYS_COREBOOT) += coreboot_car.o + +SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB):	$(OBJS) +	$(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/x86/cpu/coreboot/asm-offsets.c b/arch/x86/cpu/coreboot/asm-offsets.c new file mode 100644 index 000000000..97937da8e --- /dev/null +++ b/arch/x86/cpu/coreboot/asm-offsets.c @@ -0,0 +1,25 @@ +/* + * Adapted from Linux v2.6.36 kernel: arch/powerpc/kernel/asm-offsets.c + * + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + * + * 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. + */ + +#include <common.h> +#include <linux/kbuild.h> + +int main(void) +{ +	DEFINE(GENERATED_GD_RELOC_OFF, offsetof(gd_t, reloc_off)); +	return 0; +} diff --git a/arch/x86/cpu/coreboot/coreboot_car.S b/arch/x86/cpu/coreboot/coreboot_car.S new file mode 100644 index 000000000..3cc25755f --- /dev/null +++ b/arch/x86/cpu/coreboot/coreboot_car.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010-2011 + * Graeme Russ, <graeme.russ@gmail.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +.section .text + +.globl car_init +car_init: +	jmp	car_init_ret diff --git a/arch/x86/cpu/coreboot/ipchecksum.c b/arch/x86/cpu/coreboot/ipchecksum.c new file mode 100644 index 000000000..57733d8f0 --- /dev/null +++ b/arch/x86/cpu/coreboot/ipchecksum.c @@ -0,0 +1,54 @@ +/* + * 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 <compiler.h> +#include <asm/arch-coreboot/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; +} diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c new file mode 100644 index 000000000..f8fdac631 --- /dev/null +++ b/arch/x86/cpu/coreboot/sdram.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 + * Graeme Russ, <graeme.russ@gmail.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <asm/e820.h> +#include <asm/u-boot-x86.h> +#include <asm/global_data.h> +#include <asm/arch-coreboot/sysinfo.h> +#include <asm/arch-coreboot/tables.h> + +DECLARE_GLOBAL_DATA_PTR; + +unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) +{ +	int i; + +	unsigned num_entries = min(lib_sysinfo.n_memranges, max_entries); +	if (num_entries < lib_sysinfo.n_memranges) { +		printf("Warning: Limiting e820 map to %d entries.\n", +			num_entries); +	} +	for (i = 0; i < num_entries; i++) { +		struct memrange *memrange = &lib_sysinfo.memrange[i]; + +		entries[i].addr = memrange->base; +		entries[i].size = memrange->size; +		entries[i].type = memrange->type; +	} +	return num_entries; +} + +int dram_init_f(void) +{ +	int i; +	phys_size_t ram_size = 0; + +	for (i = 0; i < lib_sysinfo.n_memranges; i++) { +		struct memrange *memrange = &lib_sysinfo.memrange[i]; +		unsigned long long end = memrange->base + memrange->size; + +		if (memrange->type == CB_MEM_RAM && end > ram_size) +			ram_size = end; +	} +	gd->ram_size = ram_size; +	if (ram_size == 0) +		return -1; +	return 0; +} + +int dram_init(void) +{ +	return 0; +} diff --git a/arch/x86/cpu/coreboot/sysinfo.c b/arch/x86/cpu/coreboot/sysinfo.c new file mode 100644 index 000000000..9b3e660dd --- /dev/null +++ b/arch/x86/cpu/coreboot/sysinfo.c @@ -0,0 +1,39 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * 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 <asm/arch-coreboot/sysinfo.h> + +/* + * This needs to be in the .data section so that it's copied over during + * relocation. By default it's put in the .bss section which is simply filled + * with zeroes when transitioning from "ROM", which is really RAM, to other + * RAM. + */ +struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c new file mode 100644 index 000000000..0e3451bb2 --- /dev/null +++ b/arch/x86/cpu/coreboot/tables.c @@ -0,0 +1,183 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * 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 <asm/arch-coreboot/ipchecksum.h> +#include <asm/arch-coreboot/sysinfo.h> +#include <asm/arch-coreboot/tables.h> + +/* + * Some of this is x86 specific, and the rest of it is generic. Right now, + * since we only support x86, we'll avoid trying to make lots of infrastructure + * we don't need. If in the future, we want to use coreboot on some other + * architecture, then take out the generic parsing code and move it elsewhere. + */ + +/* === Parsing code === */ +/* This is the generic parsing code. */ + +static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) +{ +	struct cb_memory *mem = (struct cb_memory *)ptr; +	int count = MEM_RANGE_COUNT(mem); +	int i; + +	if (count > SYSINFO_MAX_MEM_RANGES) +		count = SYSINFO_MAX_MEM_RANGES; + +	info->n_memranges = 0; + +	for (i = 0; i < count; i++) { +		struct cb_memory_range *range = +		    (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); + +		info->memrange[info->n_memranges].base = +		    UNPACK_CB64(range->start); + +		info->memrange[info->n_memranges].size = +		    UNPACK_CB64(range->size); + +		info->memrange[info->n_memranges].type = range->type; + +		info->n_memranges++; +	} +} + +static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info) +{ +	struct cb_serial *ser = (struct cb_serial *)ptr; +	if (ser->type != CB_SERIAL_TYPE_IO_MAPPED) +		return; +	info->ser_ioport = ser->baseaddr; +} + +static void cb_parse_optiontable(unsigned char *ptr, struct sysinfo_t *info) +{ +	info->option_table = (struct cb_cmos_option_table *)ptr; +} + +static void cb_parse_checksum(unsigned char *ptr, struct sysinfo_t *info) +{ +	struct cb_cmos_checksum *cmos_cksum = (struct cb_cmos_checksum *)ptr; +	info->cmos_range_start = cmos_cksum->range_start; +	info->cmos_range_end = cmos_cksum->range_end; +	info->cmos_checksum_location = cmos_cksum->location; +} + +static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info) +{ +	info->framebuffer = (struct cb_framebuffer *)ptr; +} + +static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +{ +	struct cb_header *header; +	unsigned char *ptr = (unsigned char *)addr; +	int i; + +	for (i = 0; i < len; i += 16, ptr += 16) { +		header = (struct cb_header *)ptr; +		if (!strncmp((const char *)header->signature, "LBIO", 4)) +			break; +	} + +	/* We walked the entire space and didn't find anything. */ +	if (i >= len) +		return -1; + +	if (!header->table_bytes) +		return 0; + +	/* Make sure the checksums match. */ +	if (ipchksum((u16 *) header, sizeof(*header)) != 0) +		return -1; + +	if (ipchksum((u16 *) (ptr + sizeof(*header)), +		     header->table_bytes) != header->table_checksum) +		return -1; + +	/* Now, walk the tables. */ +	ptr += header->header_bytes; + +	for (i = 0; i < header->table_entries; i++) { +		struct cb_record *rec = (struct cb_record *)ptr; + +		/* We only care about a few tags here (maybe more later). */ +		switch (rec->tag) { +		case CB_TAG_FORWARD: +			return cb_parse_header( +				(void *)(unsigned long) +				((struct cb_forward *)rec)->forward, +				len, info); +			continue; +		case CB_TAG_MEMORY: +			cb_parse_memory(ptr, info); +			break; +		case CB_TAG_SERIAL: +			cb_parse_serial(ptr, info); +			break; +		case CB_TAG_CMOS_OPTION_TABLE: +			cb_parse_optiontable(ptr, info); +			break; +		case CB_TAG_OPTION_CHECKSUM: +			cb_parse_checksum(ptr, info); +			break; +		/* +		 * FIXME we should warn on serial if coreboot set up a +		 * framebuffer buf the payload does not know about it. +		 */ +		case CB_TAG_FRAMEBUFFER: +			cb_parse_framebuffer(ptr, info); +			break; +		} + +		ptr += rec->size; +	} + +	return 1; +} + +/* == Architecture specific == */ +/* This is the x86 specific stuff. */ + +/* Assume no translation or that memory is identity mapped. */ +static void *phys_to_virt(unsigned long virt) +{ +	return (void *)(uintptr_t)virt; +} + +int get_coreboot_info(struct sysinfo_t *info) +{ +	int ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info); + +	if (ret != 1) +		ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info); + +	return (ret == 1) ? 0 : -1; +} diff --git a/arch/x86/include/asm/arch-coreboot/ipchecksum.h b/arch/x86/include/asm/arch-coreboot/ipchecksum.h new file mode 100644 index 000000000..1d73b4d91 --- /dev/null +++ b/arch/x86/include/asm/arch-coreboot/ipchecksum.h @@ -0,0 +1,37 @@ +/* + * 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 diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h new file mode 100644 index 000000000..5c44e1a47 --- /dev/null +++ b/arch/x86/include/asm/arch-coreboot/sysinfo.h @@ -0,0 +1,63 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * 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_SYSINFO_H +#define _COREBOOT_SYSINFO_H + +#include <compiler.h> + +/* Allow a maximum of 16 memory range definitions. */ +#define SYSINFO_MAX_MEM_RANGES 16 + +struct sysinfo_t { +	unsigned int cpu_khz; +	unsigned short ser_ioport; +	unsigned long ser_base; /* for mmapped serial */ + +	int n_memranges; + +	struct memrange { +		unsigned long long base; +		unsigned long long size; +		unsigned int type; +	} memrange[SYSINFO_MAX_MEM_RANGES]; + +	struct cb_cmos_option_table *option_table; +	u32 cmos_range_start; +	u32 cmos_range_end; +	u32 cmos_checksum_location; + +	struct cb_framebuffer *framebuffer; + +	unsigned long *mbtable; /** Pointer to the multiboot table */ +}; + +extern struct sysinfo_t lib_sysinfo; + +#endif diff --git a/arch/x86/include/asm/arch-coreboot/tables.h b/arch/x86/include/asm/arch-coreboot/tables.h new file mode 100644 index 000000000..c28697375 --- /dev/null +++ b/arch/x86/include/asm/arch-coreboot/tables.h @@ -0,0 +1,241 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * 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_TABLES_H +#define _COREBOOT_TABLES_H + +#include <compiler.h> + +struct cbuint64 { +	u32 lo; +	u32 hi; +}; + +struct cb_header { +	u8 signature[4]; +	u32 header_bytes; +	u32 header_checksum; +	u32 table_bytes; +	u32 table_checksum; +	u32 table_entries; +}; + +struct cb_record { +	u32 tag; +	u32 size; +}; + +#define CB_TAG_UNUSED     0x0000 +#define CB_TAG_MEMORY     0x0001 + +struct cb_memory_range { +	struct cbuint64 start; +	struct cbuint64 size; +	u32 type; +}; + +#define CB_MEM_RAM          1 +#define CB_MEM_RESERVED     2 +#define CB_MEM_ACPI         3 +#define CB_MEM_NVS          4 +#define CB_MEM_UNUSABLE     5 +#define CB_MEM_VENDOR_RSVD  6 +#define CB_MEM_TABLE       16 + +struct cb_memory { +	u32 tag; +	u32 size; +	struct cb_memory_range map[0]; +}; + +#define CB_TAG_HWRPB      0x0002 + +struct cb_hwrpb { +	u32 tag; +	u32 size; +	u64 hwrpb; +}; + +#define CB_TAG_MAINBOARD  0x0003 + +struct cb_mainboard { +	u32 tag; +	u32 size; +	u8 vendor_idx; +	u8 part_number_idx; +	u8 strings[0]; +}; + +#define CB_TAG_VERSION        0x0004 +#define CB_TAG_EXTRA_VERSION  0x0005 +#define CB_TAG_BUILD          0x0006 +#define CB_TAG_COMPILE_TIME   0x0007 +#define CB_TAG_COMPILE_BY     0x0008 +#define CB_TAG_COMPILE_HOST   0x0009 +#define CB_TAG_COMPILE_DOMAIN 0x000a +#define CB_TAG_COMPILER       0x000b +#define CB_TAG_LINKER         0x000c +#define CB_TAG_ASSEMBLER      0x000d + +struct cb_string { +	u32 tag; +	u32 size; +	u8 string[0]; +}; + +#define CB_TAG_SERIAL         0x000f + +struct cb_serial { +	u32 tag; +	u32 size; +#define CB_SERIAL_TYPE_IO_MAPPED     1 +#define CB_SERIAL_TYPE_MEMORY_MAPPED 2 +	u32 type; +	u32 baseaddr; +	u32 baud; +}; + +#define CB_TAG_CONSOLE       0x00010 + +struct cb_console { +	u32 tag; +	u32 size; +	u16 type; +}; + +#define CB_TAG_CONSOLE_SERIAL8250 0 +#define CB_TAG_CONSOLE_VGA        1 /* OBSOLETE */ +#define CB_TAG_CONSOLE_BTEXT      2 /* OBSOLETE */ +#define CB_TAG_CONSOLE_LOGBUF     3 +#define CB_TAG_CONSOLE_SROM       4 /* OBSOLETE */ +#define CB_TAG_CONSOLE_EHCI       5 + +#define CB_TAG_FORWARD       0x00011 + +struct cb_forward { +	u32 tag; +	u32 size; +	u64 forward; +}; + +#define CB_TAG_FRAMEBUFFER      0x0012 +struct cb_framebuffer { +	u32 tag; +	u32 size; + +	u64 physical_address; +	u32 x_resolution; +	u32 y_resolution; +	u32 bytes_per_line; +	u8 bits_per_pixel; +	u8 red_mask_pos; +	u8 red_mask_size; +	u8 green_mask_pos; +	u8 green_mask_size; +	u8 blue_mask_pos; +	u8 blue_mask_size; +	u8 reserved_mask_pos; +	u8 reserved_mask_size; +}; + +#define CB_TAG_CMOS_OPTION_TABLE 0x00c8 +struct cb_cmos_option_table { +	u32 tag; +	u32 size; +	u32 header_length; +}; + +#define CB_TAG_OPTION         0x00c9 +#define CMOS_MAX_NAME_LENGTH    32 +struct cb_cmos_entries { +	u32 tag; +	u32 size; +	u32 bit; +	u32 length; +	u32 config; +	u32 config_id; +	u8 name[CMOS_MAX_NAME_LENGTH]; +}; + + +#define CB_TAG_OPTION_ENUM    0x00ca +#define CMOS_MAX_TEXT_LENGTH 32 +struct cb_cmos_enums { +	u32 tag; +	u32 size; +	u32 config_id; +	u32 value; +	u8 text[CMOS_MAX_TEXT_LENGTH]; +}; + +#define CB_TAG_OPTION_DEFAULTS 0x00cb +#define CMOS_IMAGE_BUFFER_SIZE 128 +struct cb_cmos_defaults { +	u32 tag; +	u32 size; +	u32 name_length; +	u8 name[CMOS_MAX_NAME_LENGTH]; +	u8 default_set[CMOS_IMAGE_BUFFER_SIZE]; +}; + +#define CB_TAG_OPTION_CHECKSUM 0x00cc +#define CHECKSUM_NONE	0 +#define CHECKSUM_PCBIOS	1 +struct	cb_cmos_checksum { +	u32 tag; +	u32 size; +	u32 range_start; +	u32 range_end; +	u32 location; +	u32 type; +}; + +/* Helpful macros */ + +#define MEM_RANGE_COUNT(_rec) \ +	(((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) + +#define MEM_RANGE_PTR(_rec, _idx) \ +	(((u8 *) (_rec)) + sizeof(*(_rec)) \ +	+ (sizeof((_rec)->map[0]) * (_idx))) + +#define MB_VENDOR_STRING(_mb) \ +	(((unsigned char *) ((_mb)->strings)) + (_mb)->vendor_idx) + +#define MB_PART_STRING(_mb) \ +	(((unsigned char *) ((_mb)->strings)) + (_mb)->part_number_idx) + +#define UNPACK_CB64(_in) \ +	((((u64) _in.hi) << 32) | _in.lo) + +struct sysinfo_t; + +int get_coreboot_info(struct sysinfo_t *info); + +#endif diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index a02637ff6..f03ea809a 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -24,30 +24,12 @@  #ifndef _ASM_ZIMAGE_H_  #define _ASM_ZIMAGE_H_ +#include <asm/bootparam.h> +#include <asm/e820.h> +  /* linux i386 zImage/bzImage header. Offsets relative to   * the start of the image */ -#define CMD_LINE_MAGIC_OFF  0x020 /* Magic 0xa33f if the offset below is valid */ -#define CMD_LINE_OFFSET_OFF 0x022 /* Offset to comandline */ -#define SETUP_SECTS_OFF     0x1F1 /* The size of the setup in sectors */ -#define ROOT_FLAGS_OFF      0x1F2 /* If set, the root is mounted readonly */ -#define VID_MODE_OFF        0x1FA /* Video mode control */ -#define ROOT_DEV_OFF        0x1FC /* Default root device number */ -#define BOOT_FLAG_OFF       0x1FE /* 0xAA55 magic number */ -#define HEADER_OFF          0x202 /* Magic signature "HdrS" */ -#define VERSION_OFF         0x206 /* Boot protocol version supported */ -#define REALMODE_SWTCH_OFF  0x208 /* Boot loader hook (see below) */ -#define START_SYS_OFF       0x20C /* Points to kernel version string */ -#define TYPE_OF_LOADER_OFF  0x210 /* Boot loader identifier */ -#define LOADFLAGS_OFF       0x211 /* Boot protocol option flags */ -#define SETUP_MOVE_SIZE_OFF 0x212 /* Move to high memory size (used with hooks) */ -#define CODE32_START_OFF    0x214 /* Boot loader hook (see below) */ -#define RAMDISK_IMAGE_OFF   0x218 /* initrd load address (set by boot loader) */ -#define RAMDISK_SIZE_OFF    0x21C /* initrd size (set by boot loader) */ -#define HEAP_END_PTR_OFF    0x224 /* Free memory after setup end */ -#define CMD_LINE_PTR_OFF    0x228 /* 32-bit pointer to the kernel command line */ - -  #define HEAP_FLAG           0x80  #define BIG_KERNEL_FLAG     0x01 @@ -65,10 +47,14 @@  #define BZIMAGE_LOAD_ADDR  0x100000  #define ZIMAGE_LOAD_ADDR   0x10000 -void *load_zimage(char *image, unsigned long kernel_size, -		  unsigned long initrd_addr, unsigned long initrd_size, -		  int auto_boot); +/* Implementation defined function to install an e820 map. */ +unsigned install_e820_map(unsigned max_entries, struct e820entry *); + +struct boot_params *load_zimage(char *image, unsigned long kernel_size, +				void **load_address); +int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, +		 unsigned long initrd_addr, unsigned long initrd_size); -void boot_zimage(void *setup_base); +void boot_zimage(void *setup_base, void *load_address);  #endif diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index bac7b4f0c..83caf6bdb 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -28,16 +28,20 @@  #include <command.h>  #include <image.h>  #include <u-boot/zlib.h> +#include <asm/bootparam.h>  #include <asm/byteorder.h>  #include <asm/zimage.h> +#define COMMAND_LINE_OFFSET 0x9000 +  /*cmd_boot.c*/  int do_bootm_linux(int flag, int argc, char * const argv[],  		bootm_headers_t *images)  { -	void		*base_ptr = NULL; -	ulong		os_data, os_len; -	image_header_t	*hdr; +	struct boot_params *base_ptr = NULL; +	ulong os_data, os_len; +	image_header_t *hdr; +	void *load_address;  #if defined(CONFIG_FIT)  	const void	*data; @@ -74,14 +78,19 @@ int do_bootm_linux(int flag, int argc, char * const argv[],  	}  #ifdef CONFIG_CMD_ZBOOT -	base_ptr = load_zimage((void *)os_data, os_len, -			images->rd_start, images->rd_end - images->rd_start, 0); +	base_ptr = load_zimage((void *)os_data, os_len, &load_address);  #endif  	if (NULL == base_ptr) {  		printf("## Kernel loading failed ...\n");  		goto error; +	} +	if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, +			0, images->rd_start, +			images->rd_end - images->rd_start)) { +		printf("## Setting up boot parameters failed ...\n"); +		goto error;  	}  #ifdef DEBUG @@ -92,7 +101,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[],  	/* we assume that the kernel is in place */  	printf("\nStarting kernel ...\n\n"); -	boot_zimage(base_ptr); +	boot_zimage(base_ptr, load_address);  	/* does not return */  error: diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 8b42b5caf..bb4051717 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -1,4 +1,5 @@  /* + * Copyright (c) 2011 The Chromium OS Authors.   * (C) Copyright 2002   * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>   * @@ -51,6 +52,16 @@  #define COMMAND_LINE_SIZE	2048 +unsigned generic_install_e820_map(unsigned max_entries, +				  struct e820entry *entries) +{ +	return 0; +} + +unsigned install_e820_map(unsigned max_entries, +			  struct e820entry *entries) +	__attribute__((weak, alias("generic_install_e820_map"))); +  static void build_command_line(char *command_line, int auto_boot)  {  	char *env_command_line; @@ -78,40 +89,47 @@ static void build_command_line(char *command_line, int auto_boot)  	printf("Kernel command line: \"%s\"\n", command_line);  } -void *load_zimage(char *image, unsigned long kernel_size, -		  unsigned long initrd_addr, unsigned long initrd_size, -		  int auto_boot) +static int kernel_magic_ok(struct setup_header *hdr)  { -	void *setup_base; -	int setup_size; -	int bootproto; -	int big_image; -	void *load_address; -	struct setup_header *hdr; - -	hdr = (struct setup_header *)(image + SETUP_SECTS_OFF); - -	/* base address for real-mode segment */ -	setup_base = (void *)DEFAULT_SETUP_BASE; -  	if (KERNEL_MAGIC != hdr->boot_flag) { -		printf("Error: Invalid Boot Flag (found 0x%04x, expected 0x%04x)\n", -		       hdr->boot_flag, KERNEL_MAGIC); +		printf("Error: Invalid Boot Flag " +			"(found 0x%04x, expected 0x%04x)\n", +			hdr->boot_flag, KERNEL_MAGIC);  		return 0;  	} else {  		printf("Valid Boot Flag\n"); +		return 1;  	} +} -	/* determine boot protocol version */ -	if (KERNEL_V2_MAGIC == hdr->header) { +static int get_boot_protocol(struct setup_header *hdr) +{ +	if (hdr->header == KERNEL_V2_MAGIC) {  		printf("Magic signature found\n"); - -		bootproto = hdr->version; +		return hdr->version;  	} else {  		/* Very old kernel */  		printf("Magic signature not found\n"); -		bootproto = 0x0100; +		return 0x0100;  	} +} + +struct boot_params *load_zimage(char *image, unsigned long kernel_size, +				void **load_address) +{ +	struct boot_params *setup_base; +	int setup_size; +	int bootproto; +	int big_image; + +	struct boot_params *params = (struct boot_params *)image; +	struct setup_header *hdr = ¶ms->hdr; + +	/* base address for real-mode segment */ +	setup_base = (struct boot_params *)DEFAULT_SETUP_BASE; + +	if (!kernel_magic_ok(hdr)) +		return 0;  	/* determine size of setup */  	if (0 == hdr->setup_sects) { @@ -126,27 +144,50 @@ void *load_zimage(char *image, unsigned long kernel_size,  	if (setup_size > SETUP_MAX_SIZE)  		printf("Error: Setup is too large (%d bytes)\n", setup_size); +	/* determine boot protocol version */ +	bootproto = get_boot_protocol(hdr); + +	printf("Using boot protocol version %x.%02x\n", +	       (bootproto & 0xff00) >> 8, bootproto & 0xff); + +	if (bootproto >= 0x0200) { +		if (hdr->setup_sects >= 15) { +			printf("Linux kernel version %s\n", +				(char *)params + +				hdr->kernel_version + 0x200); +		} else { +			printf("Setup Sectors < 15 - " +				"Cannot print kernel version.\n"); +		} +	} +  	/* Determine image type */  	big_image = (bootproto >= 0x0200) &&  		    (hdr->loadflags & BIG_KERNEL_FLAG);  	/* Determine load address */ -	load_address = (void *)(big_image ? -				BZIMAGE_LOAD_ADDR : -				ZIMAGE_LOAD_ADDR); +	if (big_image) +		*load_address = (void *)BZIMAGE_LOAD_ADDR; +	else +		*load_address = (void *)ZIMAGE_LOAD_ADDR; +#if defined CONFIG_ZBOOT_32 +	printf("Building boot_params at 0x%8.8lx\n", (ulong)setup_base); +	memset(setup_base, 0, sizeof(*setup_base)); +	setup_base->hdr = params->hdr; +#else  	/* load setup */  	printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n",  	       (ulong)setup_base, setup_size);  	memmove(setup_base, image, setup_size); +#endif -	printf("Using boot protocol version %x.%02x\n", -	       (bootproto & 0xff00) >> 8, bootproto & 0xff); +	if (bootproto >= 0x0204) +		kernel_size = hdr->syssize * 16; +	else +		kernel_size -= setup_size;  	if (bootproto == 0x0100) { -		*(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; -		*(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; -  		/*  		 * A very old kernel MUST have its real-mode code  		 * loaded at 0x90000 @@ -157,33 +198,60 @@ void *load_zimage(char *image, unsigned long kernel_size,  			/* Copy the command line */  			memmove((void *)0x99000, -				setup_base + COMMAND_LINE_OFFSET, +				(u8 *)setup_base + COMMAND_LINE_OFFSET,  				COMMAND_LINE_SIZE);  			 /* Relocated */ -			setup_base = (void *)0x90000; +			setup_base = (struct boot_params *)0x90000;  		}  		/* It is recommended to clear memory up to the 32K mark */ -		memset((void *)0x90000 + setup_size, 0, -		       SETUP_MAX_SIZE-setup_size); +		memset((u8 *)0x90000 + setup_size, 0, +		       SETUP_MAX_SIZE - setup_size); +	} + +	if (big_image) { +		if (kernel_size > BZIMAGE_MAX_SIZE) { +			printf("Error: bzImage kernel too big! " +				"(size: %ld, max: %d)\n", +				kernel_size, BZIMAGE_MAX_SIZE); +			return 0; +		} +	} else if ((kernel_size) > ZIMAGE_MAX_SIZE) { +		printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", +		       kernel_size, ZIMAGE_MAX_SIZE); +		return 0;  	} -	/* We are now setting up the real-mode version of the header */ -	hdr = (struct setup_header *)(setup_base + SETUP_SECTS_OFF); +	printf("Loading %s at address %p (%ld bytes)\n", +		big_image ? "bzImage" : "zImage", *load_address, kernel_size); + +	memmove(*load_address, image + setup_size, kernel_size); +	return setup_base; +} + +int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, +		 unsigned long initrd_addr, unsigned long initrd_size) +{ +	struct setup_header *hdr = &setup_base->hdr; +	int bootproto = get_boot_protocol(hdr); + +#if defined CONFIG_ZBOOT_32 +	setup_base->e820_entries = install_e820_map( +		ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); +#endif + +	if (bootproto == 0x0100) { +		setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; +		setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET; +	}  	if (bootproto >= 0x0200) {  		hdr->type_of_loader = 8; -		if (hdr->setup_sects >= 15) -			printf("Linux kernel version %s\n", -			       (char *)(setup_base + -					(hdr->kernel_version + 0x200))); -		else -			printf("Setup Sectors < 15 - Cannot print kernel version.\n"); -  		if (initrd_addr) { -			printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n", +			printf("Initial RAM disk at linear address " +			       "0x%08lx, size %ld bytes\n",  			       initrd_addr, initrd_size);  			hdr->ramdisk_image = initrd_addr; @@ -197,49 +265,42 @@ void *load_zimage(char *image, unsigned long kernel_size,  	}  	if (bootproto >= 0x0202) { -		hdr->cmd_line_ptr = (u32)setup_base + COMMAND_LINE_OFFSET; +		hdr->cmd_line_ptr = (uintptr_t)cmd_line;  	} else if (bootproto >= 0x0200) { - -		*(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; -		*(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; +		setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; +		setup_base->screen_info.cl_offset = +			(uintptr_t)cmd_line - (uintptr_t)setup_base;  		hdr->setup_move_size = 0x9100;  	} -	if (bootproto >= 0x0204) -		kernel_size = hdr->syssize * 16; -	else -		kernel_size -= setup_size; - - -	if (big_image) { -		if ((kernel_size) > BZIMAGE_MAX_SIZE) { -			printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n", -			       kernel_size, BZIMAGE_MAX_SIZE); -			return 0; -		} - -	} else if ((kernel_size) > ZIMAGE_MAX_SIZE) { -		printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", -		       kernel_size, ZIMAGE_MAX_SIZE); -		return 0; -	} -  	/* build command line at COMMAND_LINE_OFFSET */ -	build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot); - -	printf("Loading %czImage at address 0x%08x (%ld bytes)\n", -	       big_image ? 'b' : ' ', (u32)load_address, kernel_size); - - -	memmove(load_address, image + setup_size, kernel_size); - -	/* ready for booting */ -	return setup_base; +	build_command_line(cmd_line, auto_boot); +	return 0;  } -void boot_zimage(void *setup_base) +void boot_zimage(void *setup_base, void *load_address)  { +	printf("\nStarting kernel ...\n\n"); + +#if defined CONFIG_ZBOOT_32 +	/* +	 * Set %ebx, %ebp, and %edi to 0, %esi to point to the boot_params +	 * structure, and then jump to the kernel. We assume that %cs is +	 * 0x10, 4GB flat, and read/execute, and the data segments are 0x18, +	 * 4GB flat, and read/write. U-boot is setting them up that way for +	 * itself in arch/i386/cpu/cpu.c. +	 */ +	__asm__ __volatile__ ( +	"movl $0, %%ebp		\n" +	"cli			\n" +	"jmp %[kernel_entry]	\n" +	:: [kernel_entry]"a"(load_address), +	   [boot_params] "S"(setup_base), +	   "b"(0), "D"(0) +	:  "%ebp" +	); +#else  	struct pt_regs regs;  	memset(®s, 0, sizeof(struct pt_regs)); @@ -248,56 +309,79 @@ void boot_zimage(void *setup_base)  	regs.xss = regs.xds;  	regs.esp = 0x9000;  	regs.eflags = 0; -	enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, -		       ®s); +	enter_realmode(((u32)setup_base + SETUP_START_OFFSET) >> 4, 0, +		       ®s, ®s); +#endif  }  int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])  { -	void *base_ptr; +	struct boot_params *base_ptr;  	void *bzImage_addr = NULL; +	void *load_address;  	char *s;  	ulong bzImage_size = 0; +	ulong initrd_addr = 0; +	ulong initrd_size = 0;  	disable_interrupts();  	/* Setup board for maximum PC/AT Compatibility */  	setup_pcat_compatibility(); -	if (argc >= 2) +	if (argc >= 2) {  		/* argv[1] holds the address of the bzImage */  		s = argv[1]; -	else +	} else {  		s = getenv("fileaddr"); +	}  	if (s)  		bzImage_addr = (void *)simple_strtoul(s, NULL, 16); -	if (argc >= 3) +	if (argc >= 3) {  		/* argv[2] holds the size of the bzImage */  		bzImage_size = simple_strtoul(argv[2], NULL, 16); +	} + +	if (argc >= 4) +		initrd_addr = simple_strtoul(argv[3], NULL, 16); +	if (argc >= 5) +		initrd_size = simple_strtoul(argv[4], NULL, 16); -	/* Lets look for*/ -	base_ptr = load_zimage(bzImage_addr, bzImage_size, 0, 0, 0); +	/* Lets look for */ +	base_ptr = load_zimage(bzImage_addr, bzImage_size, &load_address);  	if (!base_ptr) {  		printf("## Kernel loading failed ...\n"); -	} else { -		printf("## Transferring control to Linux (at address %08x) ...\n", -			(u32)base_ptr); +		return -1; +	} +	if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, +			0, initrd_addr, initrd_size)) { +		printf("Setting up boot parameters failed ...\n"); +		return -1; +	} -		/* we assume that the kernel is in place */ -		printf("\nStarting kernel ...\n\n"); +	printf("## Transferring control to Linux " +	       "(at address %08x) ...\n", +	       (u32)base_ptr); -		boot_zimage(base_ptr); -		/* does not return */ -	} +	/* we assume that the kernel is in place */ +	boot_zimage(base_ptr, load_address); +	/* does not return */  	return -1;  }  U_BOOT_CMD( -	zboot, 2, 0,	do_zboot, +	zboot, 5, 0,	do_zboot,  	"Boot bzImage", -	"" +	"[addr] [size] [initrd addr] [initrd size]\n" +	"      addr -        The optional starting address of the bzimage.\n" +	"                    If not set it defaults to the environment\n" +	"                    variable \"fileaddr\".\n" +	"      size -        The optional size of the bzimage. Defaults to\n" +	"                    zero.\n" +	"      initrd addr - The address of the initrd image to use, if any.\n" +	"      initrd size - The size of the initrd image to use, if any.\n"  ); |