Prepare the BIOS data areas before device init.
authorDuncan Laurie <dlaurie@chromium.org>
Tue, 17 Jan 2012 17:03:11 +0000 (09:03 -0800)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Fri, 30 Mar 2012 15:51:45 +0000 (17:51 +0200)
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>
Reviewed-on: http://review.coreboot.org/769
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
src/arch/x86/include/arch/ebda.h [new file with mode: 0644]
src/arch/x86/lib/Makefile.inc
src/arch/x86/lib/ebda.c [new file with mode: 0644]
src/devices/device.c
src/devices/oprom/x86.c

diff --git a/src/arch/x86/include/arch/ebda.h b/src/arch/x86/include/arch/ebda.h
new file mode 100644 (file)
index 0000000..1de6097
--- /dev/null
@@ -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
index 96fb9b07f59da3091332d511890f8d3c8b22922c..8f5fd5f1ebda7cdfcad22deba44526565e0a88b7 100644 (file)
@@ -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 (file)
index 0000000..faf1451
--- /dev/null
@@ -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);
+}
index 0d2bf8f1ae5a3d4f891a83e4839c0776ae2e532d..0e9c39e2031d7fe77c5fc4fa8b42d23a6e5a124f 100644 (file)
@@ -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);
 
index 0c15b1560c538a485e3b44952e099eeb6f41e4f1..564017d4e4e681497d6161bc620f078fa4a088dd 100644 (file)
@@ -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();