comment and unify lb_uint64 handling as discussed on the mailinglist
[coreboot.git] / src / arch / i386 / boot / tables.c
1 #include <console/console.h>
2 #include <cpu/cpu.h>
3 #include <boot/tables.h>
4 #include <boot/linuxbios_tables.h>
5 #include <arch/pirq_routing.h>
6 #include <arch/smp/mpspec.h>
7 #include <arch/acpi.h>
8 #include "linuxbios_table.h"
9
10 // Global Descriptor Table, defined in c_start.S
11 extern uint8_t gdt;
12 extern uint8_t gdt_end;
13
14 /* i386 lgdt argument */
15 struct gdtarg {
16     unsigned short limit;
17     unsigned int base;
18 } __attribute__((packed));
19
20 // Copy GDT to new location and reload it
21 // 2003-07 by SONE Takeshi
22 // Ported from Etherboot to LinuxBIOS 2005-08 by Steve Magnani
23 void move_gdt(unsigned long newgdt)
24 {
25         uint16_t num_gdt_bytes = &gdt_end - &gdt;
26     struct gdtarg gdtarg;
27
28     printk_debug("Moving GDT to %#lx...", newgdt);
29     memcpy((void*)newgdt, &gdt, num_gdt_bytes);
30     gdtarg.base = newgdt;
31     gdtarg.limit = num_gdt_bytes - 1;
32     __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
33     printk_debug("ok\n");
34 }
35
36 struct lb_memory *write_tables(void)
37 {
38         unsigned long low_table_start, low_table_end;
39         unsigned long rom_table_start, rom_table_end;
40
41         rom_table_start = 0xf0000;
42         rom_table_end =   0xf0000;
43         /* Start low addr at 16 bytes instead of 0 because of a buglet
44          * in the generic linux unzip code, as it tests for the a20 line.
45          */
46         low_table_start = 0;
47         low_table_end = 16;
48
49         post_code(0x9a);
50
51         /* This table must be betweeen 0xf0000 & 0x100000 */
52         rom_table_end = write_pirq_routing_table(rom_table_end);
53         rom_table_end = (rom_table_end + 1023) & ~1023;
54
55         /* copy the smp block to address 0 */
56         post_code(0x96);
57
58         /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
59         low_table_end = write_smp_table(low_table_end);
60
61         /* Write ACPI tables */
62         /* write them in the rom area because DSDT can be large (8K on epia-m) which
63          * pushes linuxbios table out of first 4K if set up in low table area 
64          */
65
66         rom_table_end = write_acpi_tables(rom_table_end);
67         rom_table_end = (rom_table_end+1023) & ~1023;
68
69         /* Don't write anything in the traditional x86 BIOS data segment */
70         if (low_table_end < 0x500) {
71                 low_table_end = 0x500;
72         }
73
74         // Relocate the GDT to reserved memory, so it won't get clobbered
75         move_gdt(low_table_end);
76         low_table_end += &gdt_end - &gdt;
77
78         /* The linuxbios table must be in 0-4K or 960K-1M */
79         write_linuxbios_table(
80                               low_table_start, low_table_end,
81                               rom_table_start >> 10, rom_table_end >> 10);
82
83         return get_lb_mem();
84 }