Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 1 | ///////////////////////////////////////////////////////////////////////// |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 2 | // |
| 3 | // 32 bit Bochs BIOS init code |
| 4 | // Copyright (C) 2006 Fabrice Bellard |
| 5 | // |
| 6 | // This library is free software; you can redistribute it and/or |
| 7 | // modify it under the terms of the GNU Lesser General Public |
| 8 | // License as published by the Free Software Foundation; either |
| 9 | // version 2 of the License, or (at your option) any later version. |
| 10 | // |
| 11 | // This library is distributed in the hope that it will be useful, |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | // Lesser General Public License for more details. |
| 15 | // |
| 16 | // You should have received a copy of the GNU Lesser General Public |
| 17 | // License along with this library; if not, write to the Free Software |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 20 | #include "util.h" // dprintf |
Kevin O'Connor | a0dc296 | 2008-03-16 14:29:32 -0400 | [diff] [blame] | 21 | #include "pci.h" // PCIDevice |
| 22 | #include "types.h" // u32 |
Kevin O'Connor | d9b0659 | 2008-05-06 20:00:12 -0400 | [diff] [blame] | 23 | #include "config.h" // CONFIG_* |
Kevin O'Connor | c781293 | 2008-06-08 23:08:12 -0400 | [diff] [blame] | 24 | #include "memmap.h" // bios_table_cur_addr |
Kevin O'Connor | 276d4a9 | 2008-06-11 22:47:01 -0400 | [diff] [blame] | 25 | #include "acpi.h" // acpi_bios_init |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 26 | |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 27 | u32 cpuid_signature; |
| 28 | u32 cpuid_features; |
| 29 | u32 cpuid_ext_features; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 30 | u8 bios_uuid[16]; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 31 | |
| 32 | void uuid_probe(void) |
| 33 | { |
Kevin O'Connor | 3129984 | 2008-07-04 04:47:09 -0400 | [diff] [blame] | 34 | // Default to UUID not set |
| 35 | memset(bios_uuid, 0, 16); |
| 36 | |
| 37 | if (! CONFIG_QEMU) |
| 38 | return; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 39 | |
| 40 | // check if backdoor port exists |
Kevin O'Connor | 3129984 | 2008-07-04 04:47:09 -0400 | [diff] [blame] | 41 | u32 eax, ebx, ecx, edx; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 42 | asm volatile ("outl %%eax, %%dx" |
Kevin O'Connor | 3129984 | 2008-07-04 04:47:09 -0400 | [diff] [blame] | 43 | : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| 44 | : "a" (0x564d5868), "c" (0xa), "d" (0x5658)); |
| 45 | if (ebx != 0x564d5868) |
| 46 | return; |
| 47 | |
| 48 | u32 *uuid_ptr = (u32 *)bios_uuid; |
| 49 | // get uuid |
| 50 | asm volatile ("outl %%eax, %%dx" |
| 51 | : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| 52 | : "a" (0x564d5868), "c" (0x13), "d" (0x5658)); |
| 53 | uuid_ptr[0] = eax; |
| 54 | uuid_ptr[1] = ebx; |
| 55 | uuid_ptr[2] = ecx; |
| 56 | uuid_ptr[3] = edx; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | void cpu_probe(void) |
| 60 | { |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 61 | u32 eax, ebx, ecx, edx; |
Kevin O'Connor | 84ad59a | 2008-07-04 05:47:26 -0400 | [diff] [blame^] | 62 | cpuid(1, &eax, &ebx, &ecx, &edx); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 63 | cpuid_signature = eax; |
| 64 | cpuid_features = edx; |
| 65 | cpuid_ext_features = ecx; |
| 66 | } |
| 67 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 68 | /****************************************************/ |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 69 | /* PCI init */ |
| 70 | |
| 71 | #define PCI_ADDRESS_SPACE_MEM 0x00 |
| 72 | #define PCI_ADDRESS_SPACE_IO 0x01 |
| 73 | #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 |
| 74 | |
| 75 | #define PCI_ROM_SLOT 6 |
| 76 | #define PCI_NUM_REGIONS 7 |
| 77 | |
| 78 | #define PCI_DEVICES_MAX 64 |
| 79 | |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 80 | static u32 pci_bios_io_addr; |
| 81 | static u32 pci_bios_mem_addr; |
| 82 | static u32 pci_bios_bigmem_addr; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 83 | /* host irqs corresponding to PCI irqs A-D */ |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 84 | static u8 pci_irqs[4] = { 11, 9, 11, 9 }; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 85 | |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 86 | static void pci_set_io_region_addr(PCIDevice d, int region_num, u32 addr) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 87 | { |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 88 | u16 cmd; |
| 89 | u32 ofs, old_addr; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 90 | |
| 91 | if ( region_num == PCI_ROM_SLOT ) { |
| 92 | ofs = 0x30; |
| 93 | }else{ |
| 94 | ofs = 0x10 + region_num * 4; |
| 95 | } |
| 96 | |
| 97 | old_addr = pci_config_readl(d, ofs); |
| 98 | |
| 99 | pci_config_writel(d, ofs, addr); |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 100 | dprintf(1, "region %d: 0x%08x\n", region_num, addr); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 101 | |
| 102 | /* enable memory mappings */ |
| 103 | cmd = pci_config_readw(d, PCI_COMMAND); |
| 104 | if ( region_num == PCI_ROM_SLOT ) |
| 105 | cmd |= 2; |
| 106 | else if (old_addr & PCI_ADDRESS_SPACE_IO) |
| 107 | cmd |= 1; |
| 108 | else |
| 109 | cmd |= 2; |
| 110 | pci_config_writew(d, PCI_COMMAND, cmd); |
| 111 | } |
| 112 | |
| 113 | /* return the global irq number corresponding to a given device irq |
| 114 | pin. We could also use the bus number to have a more precise |
| 115 | mapping. */ |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 116 | static int pci_slot_get_pirq(PCIDevice pci_dev, int irq_num) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 117 | { |
| 118 | int slot_addend; |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 119 | slot_addend = (pci_dev.devfn >> 3) - 1; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 120 | return (irq_num + slot_addend) & 3; |
| 121 | } |
| 122 | |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 123 | static void pci_bios_init_bridges(PCIDevice d) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 124 | { |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 125 | u16 vendor_id, device_id; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 126 | |
| 127 | vendor_id = pci_config_readw(d, PCI_VENDOR_ID); |
| 128 | device_id = pci_config_readw(d, PCI_DEVICE_ID); |
| 129 | |
| 130 | if (vendor_id == 0x8086 && device_id == 0x7000) { |
| 131 | int i, irq; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 132 | u8 elcr[2]; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 133 | |
| 134 | /* PIIX3 bridge */ |
| 135 | |
| 136 | elcr[0] = 0x00; |
| 137 | elcr[1] = 0x00; |
| 138 | for(i = 0; i < 4; i++) { |
| 139 | irq = pci_irqs[i]; |
| 140 | /* set to trigger level */ |
| 141 | elcr[irq >> 3] |= (1 << (irq & 7)); |
| 142 | /* activate irq remapping in PIIX */ |
| 143 | pci_config_writeb(d, 0x60 + i, irq); |
| 144 | } |
| 145 | outb(elcr[0], 0x4d0); |
| 146 | outb(elcr[1], 0x4d1); |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 147 | dprintf(1, "PIIX3 init: elcr=%02x %02x\n", |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 148 | elcr[0], elcr[1]); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 149 | } |
| 150 | } |
| 151 | |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 152 | static void pci_bios_init_device(PCIDevice d) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 153 | { |
| 154 | int class; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 155 | u32 *paddr; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 156 | int i, pin, pic_irq, vendor_id, device_id; |
| 157 | |
| 158 | class = pci_config_readw(d, PCI_CLASS_DEVICE); |
| 159 | vendor_id = pci_config_readw(d, PCI_VENDOR_ID); |
| 160 | device_id = pci_config_readw(d, PCI_DEVICE_ID); |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 161 | dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n", |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 162 | d.bus, d.devfn, vendor_id, device_id); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 163 | switch(class) { |
| 164 | case 0x0101: |
| 165 | if (vendor_id == 0x8086 && device_id == 0x7010) { |
| 166 | /* PIIX3 IDE */ |
| 167 | pci_config_writew(d, 0x40, 0x8000); // enable IDE0 |
| 168 | pci_config_writew(d, 0x42, 0x8000); // enable IDE1 |
| 169 | goto default_map; |
| 170 | } else { |
| 171 | /* IDE: we map it as in ISA mode */ |
| 172 | pci_set_io_region_addr(d, 0, 0x1f0); |
| 173 | pci_set_io_region_addr(d, 1, 0x3f4); |
| 174 | pci_set_io_region_addr(d, 2, 0x170); |
| 175 | pci_set_io_region_addr(d, 3, 0x374); |
| 176 | } |
| 177 | break; |
| 178 | case 0x0300: |
| 179 | if (vendor_id != 0x1234) |
| 180 | goto default_map; |
| 181 | /* VGA: map frame buffer to default Bochs VBE address */ |
| 182 | pci_set_io_region_addr(d, 0, 0xE0000000); |
| 183 | break; |
| 184 | case 0x0800: |
| 185 | /* PIC */ |
| 186 | if (vendor_id == 0x1014) { |
| 187 | /* IBM */ |
| 188 | if (device_id == 0x0046 || device_id == 0xFFFF) { |
| 189 | /* MPIC & MPIC2 */ |
| 190 | pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); |
| 191 | } |
| 192 | } |
| 193 | break; |
| 194 | case 0xff00: |
| 195 | if (vendor_id == 0x0106b && |
| 196 | (device_id == 0x0017 || device_id == 0x0022)) { |
| 197 | /* macio bridge */ |
| 198 | pci_set_io_region_addr(d, 0, 0x80800000); |
| 199 | } |
| 200 | break; |
| 201 | default: |
| 202 | default_map: |
| 203 | /* default memory mappings */ |
| 204 | for(i = 0; i < PCI_NUM_REGIONS; i++) { |
| 205 | int ofs; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 206 | u32 val, size ; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 207 | |
| 208 | if (i == PCI_ROM_SLOT) |
| 209 | ofs = 0x30; |
| 210 | else |
| 211 | ofs = 0x10 + i * 4; |
| 212 | pci_config_writel(d, ofs, 0xffffffff); |
| 213 | val = pci_config_readl(d, ofs); |
| 214 | if (val != 0) { |
| 215 | size = (~(val & ~0xf)) + 1; |
| 216 | if (val & PCI_ADDRESS_SPACE_IO) |
| 217 | paddr = &pci_bios_io_addr; |
| 218 | else if (size >= 0x04000000) |
| 219 | paddr = &pci_bios_bigmem_addr; |
| 220 | else |
| 221 | paddr = &pci_bios_mem_addr; |
| 222 | *paddr = (*paddr + size - 1) & ~(size - 1); |
| 223 | pci_set_io_region_addr(d, i, *paddr); |
| 224 | *paddr += size; |
| 225 | } |
| 226 | } |
| 227 | break; |
| 228 | } |
| 229 | |
| 230 | /* map the interrupt */ |
| 231 | pin = pci_config_readb(d, PCI_INTERRUPT_PIN); |
| 232 | if (pin != 0) { |
| 233 | pin = pci_slot_get_pirq(d, pin - 1); |
| 234 | pic_irq = pci_irqs[pin]; |
| 235 | pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); |
| 236 | } |
| 237 | |
| 238 | if (vendor_id == 0x8086 && device_id == 0x7113) { |
| 239 | /* PIIX4 Power Management device (for ACPI) */ |
Kevin O'Connor | 276d4a9 | 2008-06-11 22:47:01 -0400 | [diff] [blame] | 240 | u32 pm_io_base = BUILD_PM_IO_BASE; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 241 | pci_config_writel(d, 0x40, pm_io_base | 1); |
| 242 | pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */ |
Kevin O'Connor | 276d4a9 | 2008-06-11 22:47:01 -0400 | [diff] [blame] | 243 | u32 smb_io_base = BUILD_SMB_IO_BASE; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 244 | pci_config_writel(d, 0x90, smb_io_base | 1); |
| 245 | pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */ |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 246 | } |
| 247 | } |
| 248 | |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 249 | void pci_for_each_device(void (*init_func)(PCIDevice d)) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 250 | { |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 251 | int bus, devfn; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 252 | u16 vendor_id, device_id; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 253 | |
| 254 | for(bus = 0; bus < 1; bus++) { |
| 255 | for(devfn = 0; devfn < 256; devfn++) { |
Kevin O'Connor | 0f803e4 | 2008-05-24 23:07:16 -0400 | [diff] [blame] | 256 | PCIDevice d = pci_bd(bus, devfn); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 257 | vendor_id = pci_config_readw(d, PCI_VENDOR_ID); |
| 258 | device_id = pci_config_readw(d, PCI_DEVICE_ID); |
| 259 | if (vendor_id != 0xffff || device_id != 0xffff) { |
| 260 | init_func(d); |
| 261 | } |
| 262 | } |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | void pci_bios_init(void) |
| 267 | { |
| 268 | pci_bios_io_addr = 0xc000; |
| 269 | pci_bios_mem_addr = 0xf0000000; |
Kevin O'Connor | 9571ac2 | 2008-05-17 22:20:27 -0400 | [diff] [blame] | 270 | pci_bios_bigmem_addr = GET_EBDA(ram_size); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 271 | if (pci_bios_bigmem_addr < 0x90000000) |
| 272 | pci_bios_bigmem_addr = 0x90000000; |
| 273 | |
| 274 | pci_for_each_device(pci_bios_init_bridges); |
| 275 | |
| 276 | pci_for_each_device(pci_bios_init_device); |
| 277 | } |
| 278 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 279 | /* SMBIOS entry point -- must be written to a 16-bit aligned address |
| 280 | between 0xf0000 and 0xfffff. |
| 281 | */ |
| 282 | struct smbios_entry_point { |
| 283 | char anchor_string[4]; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 284 | u8 checksum; |
| 285 | u8 length; |
| 286 | u8 smbios_major_version; |
| 287 | u8 smbios_minor_version; |
| 288 | u16 max_structure_size; |
| 289 | u8 entry_point_revision; |
| 290 | u8 formatted_area[5]; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 291 | char intermediate_anchor_string[5]; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 292 | u8 intermediate_checksum; |
| 293 | u16 structure_table_length; |
| 294 | u32 structure_table_address; |
| 295 | u16 number_of_structures; |
| 296 | u8 smbios_bcd_revision; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 297 | } __attribute__((__packed__)); |
| 298 | |
| 299 | /* This goes at the beginning of every SMBIOS structure. */ |
| 300 | struct smbios_structure_header { |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 301 | u8 type; |
| 302 | u8 length; |
| 303 | u16 handle; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 304 | } __attribute__((__packed__)); |
| 305 | |
| 306 | /* SMBIOS type 0 - BIOS Information */ |
| 307 | struct smbios_type_0 { |
| 308 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 309 | u8 vendor_str; |
| 310 | u8 bios_version_str; |
| 311 | u16 bios_starting_address_segment; |
| 312 | u8 bios_release_date_str; |
| 313 | u8 bios_rom_size; |
| 314 | u8 bios_characteristics[8]; |
| 315 | u8 bios_characteristics_extension_bytes[2]; |
| 316 | u8 system_bios_major_release; |
| 317 | u8 system_bios_minor_release; |
| 318 | u8 embedded_controller_major_release; |
| 319 | u8 embedded_controller_minor_release; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 320 | } __attribute__((__packed__)); |
| 321 | |
| 322 | /* SMBIOS type 1 - System Information */ |
| 323 | struct smbios_type_1 { |
| 324 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 325 | u8 manufacturer_str; |
| 326 | u8 product_name_str; |
| 327 | u8 version_str; |
| 328 | u8 serial_number_str; |
| 329 | u8 uuid[16]; |
| 330 | u8 wake_up_type; |
| 331 | u8 sku_number_str; |
| 332 | u8 family_str; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 333 | } __attribute__((__packed__)); |
| 334 | |
| 335 | /* SMBIOS type 3 - System Enclosure (v2.3) */ |
| 336 | struct smbios_type_3 { |
| 337 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 338 | u8 manufacturer_str; |
| 339 | u8 type; |
| 340 | u8 version_str; |
| 341 | u8 serial_number_str; |
| 342 | u8 asset_tag_number_str; |
| 343 | u8 boot_up_state; |
| 344 | u8 power_supply_state; |
| 345 | u8 thermal_state; |
| 346 | u8 security_status; |
| 347 | u32 oem_defined; |
| 348 | u8 height; |
| 349 | u8 number_of_power_cords; |
| 350 | u8 contained_element_count; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 351 | // contained elements follow |
| 352 | } __attribute__((__packed__)); |
| 353 | |
| 354 | /* SMBIOS type 4 - Processor Information (v2.0) */ |
| 355 | struct smbios_type_4 { |
| 356 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 357 | u8 socket_designation_str; |
| 358 | u8 processor_type; |
| 359 | u8 processor_family; |
| 360 | u8 processor_manufacturer_str; |
| 361 | u32 processor_id[2]; |
| 362 | u8 processor_version_str; |
| 363 | u8 voltage; |
| 364 | u16 external_clock; |
| 365 | u16 max_speed; |
| 366 | u16 current_speed; |
| 367 | u8 status; |
| 368 | u8 processor_upgrade; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 369 | } __attribute__((__packed__)); |
| 370 | |
| 371 | /* SMBIOS type 16 - Physical Memory Array |
| 372 | * Associated with one type 17 (Memory Device). |
| 373 | */ |
| 374 | struct smbios_type_16 { |
| 375 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 376 | u8 location; |
| 377 | u8 use; |
| 378 | u8 error_correction; |
| 379 | u32 maximum_capacity; |
| 380 | u16 memory_error_information_handle; |
| 381 | u16 number_of_memory_devices; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 382 | } __attribute__((__packed__)); |
| 383 | |
| 384 | /* SMBIOS type 17 - Memory Device |
| 385 | * Associated with one type 19 |
| 386 | */ |
| 387 | struct smbios_type_17 { |
| 388 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 389 | u16 physical_memory_array_handle; |
| 390 | u16 memory_error_information_handle; |
| 391 | u16 total_width; |
| 392 | u16 data_width; |
| 393 | u16 size; |
| 394 | u8 form_factor; |
| 395 | u8 device_set; |
| 396 | u8 device_locator_str; |
| 397 | u8 bank_locator_str; |
| 398 | u8 memory_type; |
| 399 | u16 type_detail; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 400 | } __attribute__((__packed__)); |
| 401 | |
| 402 | /* SMBIOS type 19 - Memory Array Mapped Address */ |
| 403 | struct smbios_type_19 { |
| 404 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 405 | u32 starting_address; |
| 406 | u32 ending_address; |
| 407 | u16 memory_array_handle; |
| 408 | u8 partition_width; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 409 | } __attribute__((__packed__)); |
| 410 | |
| 411 | /* SMBIOS type 20 - Memory Device Mapped Address */ |
| 412 | struct smbios_type_20 { |
| 413 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 414 | u32 starting_address; |
| 415 | u32 ending_address; |
| 416 | u16 memory_device_handle; |
| 417 | u16 memory_array_mapped_address_handle; |
| 418 | u8 partition_row_position; |
| 419 | u8 interleave_position; |
| 420 | u8 interleaved_data_depth; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 421 | } __attribute__((__packed__)); |
| 422 | |
| 423 | /* SMBIOS type 32 - System Boot Information */ |
| 424 | struct smbios_type_32 { |
| 425 | struct smbios_structure_header header; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 426 | u8 reserved[6]; |
| 427 | u8 boot_status; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 428 | } __attribute__((__packed__)); |
| 429 | |
| 430 | /* SMBIOS type 127 -- End-of-table */ |
| 431 | struct smbios_type_127 { |
| 432 | struct smbios_structure_header header; |
| 433 | } __attribute__((__packed__)); |
| 434 | |
| 435 | static void |
| 436 | smbios_entry_point_init(void *start, |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 437 | u16 max_structure_size, |
| 438 | u16 structure_table_length, |
| 439 | u32 structure_table_address, |
| 440 | u16 number_of_structures) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 441 | { |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 442 | struct smbios_entry_point *ep = (struct smbios_entry_point *)start; |
| 443 | |
| 444 | memcpy(ep->anchor_string, "_SM_", 4); |
| 445 | ep->length = 0x1f; |
| 446 | ep->smbios_major_version = 2; |
| 447 | ep->smbios_minor_version = 4; |
| 448 | ep->max_structure_size = max_structure_size; |
| 449 | ep->entry_point_revision = 0; |
| 450 | memset(ep->formatted_area, 0, 5); |
| 451 | memcpy(ep->intermediate_anchor_string, "_DMI_", 5); |
| 452 | |
| 453 | ep->structure_table_length = structure_table_length; |
| 454 | ep->structure_table_address = structure_table_address; |
| 455 | ep->number_of_structures = number_of_structures; |
| 456 | ep->smbios_bcd_revision = 0x24; |
| 457 | |
| 458 | ep->checksum = 0; |
| 459 | ep->intermediate_checksum = 0; |
| 460 | |
Kevin O'Connor | 2e7ab8b | 2008-03-29 14:29:35 -0400 | [diff] [blame] | 461 | ep->checksum = -checksum(start, 0x10); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 462 | |
Kevin O'Connor | 2e7ab8b | 2008-03-29 14:29:35 -0400 | [diff] [blame] | 463 | ep->intermediate_checksum = -checksum(start + 0x10, ep->length - 0x10); |
| 464 | } |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 465 | |
| 466 | /* Type 0 -- BIOS Information */ |
| 467 | #define RELEASE_DATE_STR "01/01/2007" |
| 468 | static void * |
| 469 | smbios_type_0_init(void *start) |
| 470 | { |
| 471 | struct smbios_type_0 *p = (struct smbios_type_0 *)start; |
| 472 | |
| 473 | p->header.type = 0; |
| 474 | p->header.length = sizeof(struct smbios_type_0); |
| 475 | p->header.handle = 0; |
| 476 | |
| 477 | p->vendor_str = 1; |
| 478 | p->bios_version_str = 1; |
| 479 | p->bios_starting_address_segment = 0xe800; |
| 480 | p->bios_release_date_str = 2; |
| 481 | p->bios_rom_size = 0; /* FIXME */ |
| 482 | |
| 483 | memset(p->bios_characteristics, 0, 7); |
| 484 | p->bios_characteristics[7] = 0x08; /* BIOS characteristics not supported */ |
| 485 | p->bios_characteristics_extension_bytes[0] = 0; |
| 486 | p->bios_characteristics_extension_bytes[1] = 0; |
| 487 | |
| 488 | p->system_bios_major_release = 1; |
| 489 | p->system_bios_minor_release = 0; |
| 490 | p->embedded_controller_major_release = 0xff; |
| 491 | p->embedded_controller_minor_release = 0xff; |
| 492 | |
| 493 | start += sizeof(struct smbios_type_0); |
Kevin O'Connor | d9b0659 | 2008-05-06 20:00:12 -0400 | [diff] [blame] | 494 | memcpy((char *)start, CONFIG_APPNAME, sizeof(CONFIG_APPNAME)); |
| 495 | start += sizeof(CONFIG_APPNAME); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 496 | memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR)); |
| 497 | start += sizeof(RELEASE_DATE_STR); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 498 | *((u8 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 499 | |
| 500 | return start+1; |
| 501 | } |
| 502 | |
| 503 | /* Type 1 -- System Information */ |
| 504 | static void * |
| 505 | smbios_type_1_init(void *start) |
| 506 | { |
| 507 | struct smbios_type_1 *p = (struct smbios_type_1 *)start; |
| 508 | p->header.type = 1; |
| 509 | p->header.length = sizeof(struct smbios_type_1); |
| 510 | p->header.handle = 0x100; |
| 511 | |
| 512 | p->manufacturer_str = 0; |
| 513 | p->product_name_str = 0; |
| 514 | p->version_str = 0; |
| 515 | p->serial_number_str = 0; |
| 516 | |
| 517 | memcpy(p->uuid, bios_uuid, 16); |
| 518 | |
| 519 | p->wake_up_type = 0x06; /* power switch */ |
| 520 | p->sku_number_str = 0; |
| 521 | p->family_str = 0; |
| 522 | |
| 523 | start += sizeof(struct smbios_type_1); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 524 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 525 | |
| 526 | return start+2; |
| 527 | } |
| 528 | |
| 529 | /* Type 3 -- System Enclosure */ |
| 530 | static void * |
| 531 | smbios_type_3_init(void *start) |
| 532 | { |
| 533 | struct smbios_type_3 *p = (struct smbios_type_3 *)start; |
| 534 | |
| 535 | p->header.type = 3; |
| 536 | p->header.length = sizeof(struct smbios_type_3); |
| 537 | p->header.handle = 0x300; |
| 538 | |
| 539 | p->manufacturer_str = 0; |
| 540 | p->type = 0x01; /* other */ |
| 541 | p->version_str = 0; |
| 542 | p->serial_number_str = 0; |
| 543 | p->asset_tag_number_str = 0; |
| 544 | p->boot_up_state = 0x03; /* safe */ |
| 545 | p->power_supply_state = 0x03; /* safe */ |
| 546 | p->thermal_state = 0x03; /* safe */ |
| 547 | p->security_status = 0x02; /* unknown */ |
| 548 | p->oem_defined = 0; |
| 549 | p->height = 0; |
| 550 | p->number_of_power_cords = 0; |
| 551 | p->contained_element_count = 0; |
| 552 | |
| 553 | start += sizeof(struct smbios_type_3); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 554 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 555 | |
| 556 | return start+2; |
| 557 | } |
| 558 | |
| 559 | /* Type 4 -- Processor Information */ |
| 560 | static void * |
| 561 | smbios_type_4_init(void *start, unsigned int cpu_number) |
| 562 | { |
| 563 | struct smbios_type_4 *p = (struct smbios_type_4 *)start; |
| 564 | |
| 565 | p->header.type = 4; |
| 566 | p->header.length = sizeof(struct smbios_type_4); |
| 567 | p->header.handle = 0x400 + cpu_number; |
| 568 | |
| 569 | p->socket_designation_str = 1; |
| 570 | p->processor_type = 0x03; /* CPU */ |
| 571 | p->processor_family = 0x01; /* other */ |
| 572 | p->processor_manufacturer_str = 0; |
| 573 | |
| 574 | p->processor_id[0] = cpuid_signature; |
| 575 | p->processor_id[1] = cpuid_features; |
| 576 | |
| 577 | p->processor_version_str = 0; |
| 578 | p->voltage = 0; |
| 579 | p->external_clock = 0; |
| 580 | |
| 581 | p->max_speed = 0; /* unknown */ |
| 582 | p->current_speed = 0; /* unknown */ |
| 583 | |
| 584 | p->status = 0x41; /* socket populated, CPU enabled */ |
| 585 | p->processor_upgrade = 0x01; /* other */ |
| 586 | |
| 587 | start += sizeof(struct smbios_type_4); |
| 588 | |
| 589 | memcpy((char *)start, "CPU " "\0" "" "\0" "", 7); |
| 590 | ((char *)start)[4] = cpu_number + '0'; |
| 591 | |
| 592 | return start+7; |
| 593 | } |
| 594 | |
| 595 | /* Type 16 -- Physical Memory Array */ |
| 596 | static void * |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 597 | smbios_type_16_init(void *start, u32 memsize) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 598 | { |
| 599 | struct smbios_type_16 *p = (struct smbios_type_16*)start; |
| 600 | |
| 601 | p->header.type = 16; |
| 602 | p->header.length = sizeof(struct smbios_type_16); |
| 603 | p->header.handle = 0x1000; |
| 604 | |
| 605 | p->location = 0x01; /* other */ |
| 606 | p->use = 0x03; /* system memory */ |
| 607 | p->error_correction = 0x01; /* other */ |
| 608 | p->maximum_capacity = memsize * 1024; |
| 609 | p->memory_error_information_handle = 0xfffe; /* none provided */ |
| 610 | p->number_of_memory_devices = 1; |
| 611 | |
| 612 | start += sizeof(struct smbios_type_16); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 613 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 614 | |
| 615 | return start + 2; |
| 616 | } |
| 617 | |
| 618 | /* Type 17 -- Memory Device */ |
| 619 | static void * |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 620 | smbios_type_17_init(void *start, u32 memory_size_mb) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 621 | { |
| 622 | struct smbios_type_17 *p = (struct smbios_type_17 *)start; |
| 623 | |
| 624 | p->header.type = 17; |
| 625 | p->header.length = sizeof(struct smbios_type_17); |
| 626 | p->header.handle = 0x1100; |
| 627 | |
| 628 | p->physical_memory_array_handle = 0x1000; |
| 629 | p->total_width = 64; |
| 630 | p->data_width = 64; |
| 631 | /* truncate memory_size_mb to 16 bits and clear most significant |
| 632 | bit [indicates size in MB] */ |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 633 | p->size = (u16) memory_size_mb & 0x7fff; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 634 | p->form_factor = 0x09; /* DIMM */ |
| 635 | p->device_set = 0; |
| 636 | p->device_locator_str = 1; |
| 637 | p->bank_locator_str = 0; |
| 638 | p->memory_type = 0x07; /* RAM */ |
| 639 | p->type_detail = 0; |
| 640 | |
| 641 | start += sizeof(struct smbios_type_17); |
| 642 | memcpy((char *)start, "DIMM 1", 7); |
| 643 | start += 7; |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 644 | *((u8 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 645 | |
| 646 | return start+1; |
| 647 | } |
| 648 | |
| 649 | /* Type 19 -- Memory Array Mapped Address */ |
| 650 | static void * |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 651 | smbios_type_19_init(void *start, u32 memory_size_mb) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 652 | { |
| 653 | struct smbios_type_19 *p = (struct smbios_type_19 *)start; |
| 654 | |
| 655 | p->header.type = 19; |
| 656 | p->header.length = sizeof(struct smbios_type_19); |
| 657 | p->header.handle = 0x1300; |
| 658 | |
| 659 | p->starting_address = 0; |
| 660 | p->ending_address = (memory_size_mb-1) * 1024; |
| 661 | p->memory_array_handle = 0x1000; |
| 662 | p->partition_width = 1; |
| 663 | |
| 664 | start += sizeof(struct smbios_type_19); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 665 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 666 | |
| 667 | return start + 2; |
| 668 | } |
| 669 | |
| 670 | /* Type 20 -- Memory Device Mapped Address */ |
| 671 | static void * |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 672 | smbios_type_20_init(void *start, u32 memory_size_mb) |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 673 | { |
| 674 | struct smbios_type_20 *p = (struct smbios_type_20 *)start; |
| 675 | |
| 676 | p->header.type = 20; |
| 677 | p->header.length = sizeof(struct smbios_type_20); |
| 678 | p->header.handle = 0x1400; |
| 679 | |
| 680 | p->starting_address = 0; |
| 681 | p->ending_address = (memory_size_mb-1)*1024; |
| 682 | p->memory_device_handle = 0x1100; |
| 683 | p->memory_array_mapped_address_handle = 0x1300; |
| 684 | p->partition_row_position = 1; |
| 685 | p->interleave_position = 0; |
| 686 | p->interleaved_data_depth = 0; |
| 687 | |
| 688 | start += sizeof(struct smbios_type_20); |
| 689 | |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 690 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 691 | return start+2; |
| 692 | } |
| 693 | |
| 694 | /* Type 32 -- System Boot Information */ |
| 695 | static void * |
| 696 | smbios_type_32_init(void *start) |
| 697 | { |
| 698 | struct smbios_type_32 *p = (struct smbios_type_32 *)start; |
| 699 | |
| 700 | p->header.type = 32; |
| 701 | p->header.length = sizeof(struct smbios_type_32); |
| 702 | p->header.handle = 0x2000; |
| 703 | memset(p->reserved, 0, 6); |
| 704 | p->boot_status = 0; /* no errors detected */ |
| 705 | |
| 706 | start += sizeof(struct smbios_type_32); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 707 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 708 | |
| 709 | return start+2; |
| 710 | } |
| 711 | |
| 712 | /* Type 127 -- End of Table */ |
| 713 | static void * |
| 714 | smbios_type_127_init(void *start) |
| 715 | { |
| 716 | struct smbios_type_127 *p = (struct smbios_type_127 *)start; |
| 717 | |
| 718 | p->header.type = 127; |
| 719 | p->header.length = sizeof(struct smbios_type_127); |
| 720 | p->header.handle = 0x7f00; |
| 721 | |
| 722 | start += sizeof(struct smbios_type_127); |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 723 | *((u16 *)start) = 0; |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 724 | |
| 725 | return start + 2; |
| 726 | } |
| 727 | |
| 728 | void smbios_init(void) |
| 729 | { |
| 730 | unsigned cpu_num, nr_structs = 0, max_struct_size = 0; |
| 731 | char *start, *p, *q; |
Kevin O'Connor | 9571ac2 | 2008-05-17 22:20:27 -0400 | [diff] [blame] | 732 | int memsize = GET_EBDA(ram_size) / (1024 * 1024); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 733 | |
Kevin O'Connor | 276d4a9 | 2008-06-11 22:47:01 -0400 | [diff] [blame] | 734 | bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 735 | start = (void *)(bios_table_cur_addr); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 736 | |
Kevin O'Connor | 2ad3744 | 2008-05-06 19:49:01 -0400 | [diff] [blame] | 737 | p = (char *)start + sizeof(struct smbios_entry_point); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 738 | |
| 739 | #define add_struct(fn) { \ |
| 740 | q = (fn); \ |
| 741 | nr_structs++; \ |
| 742 | if ((q - p) > max_struct_size) \ |
| 743 | max_struct_size = q - p; \ |
| 744 | p = q; \ |
| 745 | } |
| 746 | |
| 747 | add_struct(smbios_type_0_init(p)); |
| 748 | add_struct(smbios_type_1_init(p)); |
| 749 | add_struct(smbios_type_3_init(p)); |
Kevin O'Connor | 84ad59a | 2008-07-04 05:47:26 -0400 | [diff] [blame^] | 750 | int smp_cpus = smp_probe(); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 751 | for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++) |
| 752 | add_struct(smbios_type_4_init(p, cpu_num)); |
| 753 | add_struct(smbios_type_16_init(p, memsize)); |
| 754 | add_struct(smbios_type_17_init(p, memsize)); |
| 755 | add_struct(smbios_type_19_init(p, memsize)); |
| 756 | add_struct(smbios_type_20_init(p, memsize)); |
| 757 | add_struct(smbios_type_32_init(p)); |
| 758 | add_struct(smbios_type_127_init(p)); |
| 759 | |
| 760 | #undef add_struct |
| 761 | |
| 762 | smbios_entry_point_init( |
| 763 | start, max_struct_size, |
| 764 | (p - (char *)start) - sizeof(struct smbios_entry_point), |
Kevin O'Connor | e51313d | 2008-03-12 21:19:34 -0400 | [diff] [blame] | 765 | (u32)(start + sizeof(struct smbios_entry_point)), |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 766 | nr_structs); |
| 767 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 768 | bios_table_cur_addr += (p - (char *)start); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 769 | |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 770 | dprintf(1, "SMBIOS table addr=0x%08lx\n", (unsigned long)start); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 771 | } |
| 772 | |
| 773 | void rombios32_init(void) |
| 774 | { |
Kevin O'Connor | f64f0db | 2008-05-18 02:42:58 -0400 | [diff] [blame] | 775 | if (CONFIG_COREBOOT) |
| 776 | // XXX - not supported on coreboot yet. |
| 777 | return; |
| 778 | |
Kevin O'Connor | ac8df8c | 2008-05-24 23:46:33 -0400 | [diff] [blame] | 779 | dprintf(1, "Starting rombios32\n"); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 780 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 781 | cpu_probe(); |
| 782 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 783 | pci_bios_init(); |
| 784 | |
Kevin O'Connor | f7ba6d7 | 2008-07-04 05:05:54 -0400 | [diff] [blame] | 785 | smm_init(); |
| 786 | |
Kevin O'Connor | d25810a | 2008-06-12 22:16:35 -0400 | [diff] [blame] | 787 | create_pirtable(); |
| 788 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 789 | if (bios_table_cur_addr != 0) { |
| 790 | |
| 791 | mptable_init(); |
| 792 | |
Kevin O'Connor | 0227095 | 2008-05-13 22:31:39 -0400 | [diff] [blame] | 793 | uuid_probe(); |
| 794 | |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 795 | smbios_init(); |
| 796 | |
Kevin O'Connor | 276d4a9 | 2008-06-11 22:47:01 -0400 | [diff] [blame] | 797 | acpi_bios_init(); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 798 | |
Kevin O'Connor | c781293 | 2008-06-08 23:08:12 -0400 | [diff] [blame] | 799 | dprintf(1, "bios_table_cur_addr: 0x%08x\n", bios_table_cur_addr); |
Kevin O'Connor | a4d3576 | 2008-03-08 15:43:03 -0500 | [diff] [blame] | 800 | if (bios_table_cur_addr > bios_table_end_addr) |
| 801 | BX_PANIC("bios_table_end_addr overflow!\n"); |
| 802 | } |
| 803 | } |