Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/769
-gerrit
commit 73b5bba34054ac4901739c92c5235ee15e756847 Author: Duncan Laurie dlaurie@chromium.org Date: Tue Jan 17 09:03:11 2012 -0800
Prepare the BIOS data areas before device init.
Since we do not run option roms in normal mode nothing was initializing the BDA/EBDA and yet Linux depends very much on it having sane values here. For the most part the kernel tries to work around this not being initialized, but every once in awhile (1/300 boots or so) it would end up reading something that looked sane from BDA but was not and then it would panic.
In this change the EBDA is unconditionally setup before devices are initialized. I'm not set on the location in dev_initialize() but there does not seem to be another place to hook it in so that it runs just once for ALL platforms regardless of whether they use option roms or not. (possibly hardwaremain?)
The EBDA setup code has been moved into its own location in arch/x86/lib/ebda.c so it can be compiled in even if the option rom code is not.
The low memory size is still set to 1MB which is enough to make linux happy without having to hook into each mainboard to get a more appropriate value. The setup_ebda() function takes inputs so it could be changed for a mainboard if needed.
OLD/BROKEN would read garbage. Examples from different boots: ebda_addr=0x75e80 lowmem=0x1553400 ebda_addr=0x5e080 lowmem=0x3e51400 ebda_addr=0x7aa80 lowmem=0x2f8a800
NEW/FIXED now reads consistent values: ebda_addr=0xf6000 lowmem=0x100000
Change-Id: I6cb79f0e3e43cc65f7e5fe98b6cad1a557ccd949 Signed-off-by: Duncan Laurie dlaurie@google.com --- src/arch/x86/include/arch/ebda.h | 37 +++++++++++++++++++++++++++++ src/arch/x86/lib/Makefile.inc | 1 + src/arch/x86/lib/ebda.c | 48 ++++++++++++++++++++++++++++++++++++++ src/devices/device.c | 8 ++++++ src/devices/oprom/x86.c | 16 ------------ 5 files changed, 94 insertions(+), 16 deletions(-)
diff --git a/src/arch/x86/include/arch/ebda.h b/src/arch/x86/include/arch/ebda.h new file mode 100644 index 0000000..1de6097 --- /dev/null +++ b/src/arch/x86/include/arch/ebda.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * + * 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; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef __ARCH_EBDA_H +#define __ARCH_EBDA_H + +#define X86_BDA_SIZE 0x200 +#define X86_BDA_BASE 0x400 +#define X86_EBDA_SEGMENT 0x40e +#define X86_EBDA_LOWMEM 0x413 + +#define DEFAULT_EBDA_LOWMEM (1024 << 10) +#define DEFAULT_EBDA_SEGMENT 0xF600 +#define DEFAULT_EBDA_SIZE 0x400 + +void setup_ebda(u32 low_memory_size, u16 ebda_segment, u16 ebda_size); +void setup_default_ebda(void); + +#endif diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc index 96fb9b0..8f5fd5f 100644 --- a/src/arch/x86/lib/Makefile.inc +++ b/src/arch/x86/lib/Makefile.inc @@ -8,6 +8,7 @@ ramstage-y += exception.c ramstage-$(CONFIG_IOAPIC) += ioapic.c ramstage-y += memset.c ramstage-y += memcpy.c +ramstage-y += ebda.c
romstage-y += romstage_console.c romstage-y += cbfs_and_run.c diff --git a/src/arch/x86/lib/ebda.c b/src/arch/x86/lib/ebda.c new file mode 100644 index 0000000..faf1451 --- /dev/null +++ b/src/arch/x86/lib/ebda.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * + * 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; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <stdint.h> +#include <string.h> +#include <arch/io.h> +#include <arch/ebda.h> + +void setup_ebda(u32 low_memory_size, u16 ebda_segment, u16 ebda_size) +{ + if (!low_memory_size || !ebda_segment || !ebda_size) + return; + + /* clear BIOS DATA AREA */ + memset((void *)X86_BDA_BASE, 0, X86_BDA_SIZE); + + write16(X86_EBDA_LOWMEM, (low_memory_size >> 10)); + write16(X86_EBDA_SEGMENT, ebda_segment); + + /* Set up EBDA */ + memset((void *)(ebda_segment << 4), 0, ebda_size); + write16((ebda_segment << 4), (ebda_size >> 10)); +} + +void setup_default_ebda(void) +{ + setup_ebda(DEFAULT_EBDA_LOWMEM, + DEFAULT_EBDA_SEGMENT, + DEFAULT_EBDA_SIZE); +} diff --git a/src/devices/device.c b/src/devices/device.c index a2619bf..f559da5 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -41,6 +41,9 @@ #include <stdlib.h> #include <string.h> #include <smp/spinlock.h> +#if CONFIG_ARCH_X86 +#include <arch/ebda.h> +#endif
/** Linked list of ALL devices */ struct device *all_devices = &dev_root; @@ -1102,6 +1105,11 @@ void dev_initialize(void)
printk(BIOS_INFO, "Initializing devices...\n");
+#if CONFIG_ARCH_X86 + /* Ensure EBDA is prepared before Option ROMs. */ + setup_default_ebda(); +#endif + /* First call the mainboard init. */ init_dev(&dev_root);
diff --git a/src/devices/oprom/x86.c b/src/devices/oprom/x86.c index 0c15b15..564017d 100644 --- a/src/devices/oprom/x86.c +++ b/src/devices/oprom/x86.c @@ -40,19 +40,6 @@ void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx, u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_interrupt;
-static void setup_bda(void) -{ - /* clear BIOS DATA AREA */ - memset((void *)0x400, 0, 0x200); - - write16(0x413, FAKE_MEMORY_SIZE / 1024); - write16(0x40e, INITIAL_EBDA_SEGMENT); - - /* Set up EBDA */ - memset((void *)(INITIAL_EBDA_SEGMENT << 4), 0, INITIAL_EBDA_SIZE); - write16((INITIAL_EBDA_SEGMENT << 4) + 0x0, INITIAL_EBDA_SIZE / 1024); -} - static void setup_rombios(void) { const char date[] = "06/11/99"; @@ -272,9 +259,6 @@ void run_bios(struct device *dev, unsigned long addr) */ setup_i8259();
- /* Set up BIOS Data Area */ - setup_bda(); - /* Set up some legacy information in the F segment */ setup_rombios();
On 07/03/12 01:06, Stefan Reinauer (stefan.reinauer@coreboot.org) wrote:
NEW/FIXED now reads consistent values: ebda_addr=0xf6000 lowmem=0x100000
OK, now this worries me. Any time you move away from the classic PC memory map you are risking problems.
0xe0000-0xfffff would normally be for shadowed firmware. 0xc0000-0xdffff would normally be for option ROMS 0xa0000-0xbffff would normally be for legacy VGA memory
So I would expect to see the EBDA at 0x9c000 for 1KB and hence the top of usable real mode memory to be at 0x9ffff. Now I may be speaking out of turn as I have no idea how coreboot organises its memory map or how that relates to SeaBIOS etc. but unless you can guarantee that no software that will run on this machine will be upset by your values I would suggest sticking with the classic legacy values instead.
Andrew
On Wed, Mar 07, 2012 at 12:05:07PM +0000, Andrew Goodbody wrote:
On 07/03/12 01:06, Stefan Reinauer (stefan.reinauer@coreboot.org) wrote:
NEW/FIXED now reads consistent values: ebda_addr=0xf6000 lowmem=0x100000
OK, now this worries me. Any time you move away from the classic PC memory map you are risking problems.
First of all, INITIAL_EBDA_SEGMENT has been 0xF600 prior to this change.
I believe loading a SeaBIOS payload will obliterate the coreboot EBDA at this location. SeaBIOS almost certainly replaces/updates the BDA and will position its own EBDA at an appropriate place.
Jonathan Kollasch
On 07/03/12 12:37, Jonathan A. Kollasch wrote:
First of all, INITIAL_EBDA_SEGMENT has been 0xF600 prior to this change.
OK, I guess it works then. At least most of the time anyway.
I believe loading a SeaBIOS payload will obliterate the coreboot EBDA at this location. SeaBIOS almost certainly replaces/updates the BDA and will position its own EBDA at an appropriate place.
I guess there is no need to go back to coreboot code at that point so this is OK. It just seems to me that it would be neater and more consistent if the EBDA were in an appropriate place to begin with.
What is the reason to have it up at 0xf6000? Linux will boot happily with it at 0x9c000 or even somewhat lower, as it must to boot with a standard BIOS.
Andrew