1 /////////////////////////////////////////////////////////////////////////
2 // $Id: rombios32.c,v 1.22 2008/01/27 17:57:26 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // 32 bit Bochs BIOS init code
6 // Copyright (C) 2006 Fabrice Bellard
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "util.h" // BX_INFO
23 #include "cmos.h" // inb_cmos
24 #include "pci.h" // PCIDevice
25 #include "types.h" // u32
27 #define BX_APPNAME "Bochs"
29 #define ACPI_DATA_SIZE 0x00010000L
30 #define PM_IO_BASE 0xb000
31 #define SMB_IO_BASE 0xb100
32 #define CPU_COUNT_ADDR 0xf000
34 /* if true, put the MP float table and ACPI RSDT in EBDA and the MP
35 table in RAM. Unfortunately, Linux has bugs with that, so we prefer
36 to modify the BIOS in shadow RAM */
37 //#define BX_USE_EBDA_TABLES
39 /* define it if the (emulated) hardware supports SMM mode */
42 #define cpuid(index, eax, ebx, ecx, edx) \
43 asm volatile ("cpuid" \
44 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
47 #define wbinvd() asm volatile("wbinvd")
49 #define CPUID_APIC (1 << 9)
51 #define APIC_BASE ((u8 *)0xfee00000)
52 #define APIC_ICR_LOW 0x300
53 #define APIC_SVR 0x0F0
55 #define APIC_LVT3 0x370
57 #define APIC_ENABLED 0x0100
59 #define AP_BOOT_ADDR 0x10000
61 #define MPTABLE_MAX_SIZE 0x00002000
62 #define SMI_CMD_IO_ADDR 0xb2
64 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
66 static inline void writel(void *addr, u32 val)
68 *(volatile u32 *)addr = val;
71 static inline void writew(void *addr, u16 val)
73 *(volatile u16 *)addr = val;
76 static inline void writeb(void *addr, u8 val)
78 *(volatile u8 *)addr = val;
81 static inline u32 readl(const void *addr)
83 return *(volatile const u32 *)addr;
86 static inline u16 readw(const void *addr)
88 return *(volatile const u16 *)addr;
91 static inline u8 readb(const void *addr)
93 return *(volatile const u8 *)addr;
99 u32 cpuid_ext_features;
100 unsigned long ram_size;
102 #ifdef BX_USE_EBDA_TABLES
103 unsigned long ebda_cur_addr;
106 u32 pm_io_base, smb_io_base;
108 unsigned long bios_table_cur_addr;
109 unsigned long bios_table_end_addr;
111 void uuid_probe(void)
114 u32 eax, ebx, ecx, edx;
116 // check if backdoor port exists
117 asm volatile ("outl %%eax, %%dx"
118 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
119 : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
120 if (ebx == 0x564d5868) {
121 u32 *uuid_ptr = (u32 *)bios_uuid;
123 asm volatile ("outl %%eax, %%dx"
124 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
125 : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
134 memset(bios_uuid, 0, 16);
140 u32 eax, ebx, ecx, edx;
141 cpuid(1, eax, ebx, ecx, edx);
142 cpuid_signature = eax;
143 cpuid_features = edx;
144 cpuid_ext_features = ecx;
149 if (inb_cmos(0x34) | inb_cmos(0x35))
150 ram_size = (inb_cmos(0x34) | (inb_cmos(0x35) << 8)) * 65536 +
153 ram_size = (inb_cmos(0x17) | (inb_cmos(0x18) << 8)) * 1024;
154 #ifdef BX_USE_EBDA_TABLES
155 ebda_cur_addr = ((*(u16 *)(0x40e)) << 4) + 0x380;
157 BX_INFO("ram_size=0x%08lx\n", ram_size);
160 /****************************************************/
163 extern u8 smp_ap_boot_code_start;
164 extern u8 smp_ap_boot_code_end;
166 /* find the number of CPUs by launching a SIPI to them */
169 u32 val, sipi_vector;
172 if (cpuid_features & CPUID_APIC) {
174 /* enable local APIC */
175 val = readl(APIC_BASE + APIC_SVR);
177 writel(APIC_BASE + APIC_SVR, val);
179 writew((void *)CPU_COUNT_ADDR, 1);
180 /* copy AP boot code */
181 memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start,
182 &smp_ap_boot_code_end - &smp_ap_boot_code_start);
185 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500);
186 sipi_vector = AP_BOOT_ADDR >> 12;
187 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector);
191 smp_cpus = readw((void *)CPU_COUNT_ADDR);
193 BX_INFO("Found %d cpu(s)\n", smp_cpus);
196 /****************************************************/
199 #define PCI_ADDRESS_SPACE_MEM 0x00
200 #define PCI_ADDRESS_SPACE_IO 0x01
201 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
203 #define PCI_ROM_SLOT 6
204 #define PCI_NUM_REGIONS 7
206 #define PCI_DEVICES_MAX 64
208 #define PCI_VENDOR_ID 0x00 /* 16 bits */
209 #define PCI_DEVICE_ID 0x02 /* 16 bits */
210 #define PCI_COMMAND 0x04 /* 16 bits */
211 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
212 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
213 #define PCI_CLASS_DEVICE 0x0a /* Device class */
214 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
215 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
216 #define PCI_MIN_GNT 0x3e /* 8 bits */
217 #define PCI_MAX_LAT 0x3f /* 8 bits */
219 static u32 pci_bios_io_addr;
220 static u32 pci_bios_mem_addr;
221 static u32 pci_bios_bigmem_addr;
222 /* host irqs corresponding to PCI irqs A-D */
223 static u8 pci_irqs[4] = { 11, 9, 11, 9 };
224 static PCIDevice i440_pcidev;
226 static void pci_set_io_region_addr(PCIDevice *d, int region_num, u32 addr)
231 if ( region_num == PCI_ROM_SLOT ) {
234 ofs = 0x10 + region_num * 4;
237 old_addr = pci_config_readl(d, ofs);
239 pci_config_writel(d, ofs, addr);
240 BX_INFO("region %d: 0x%08x\n", region_num, addr);
242 /* enable memory mappings */
243 cmd = pci_config_readw(d, PCI_COMMAND);
244 if ( region_num == PCI_ROM_SLOT )
246 else if (old_addr & PCI_ADDRESS_SPACE_IO)
250 pci_config_writew(d, PCI_COMMAND, cmd);
253 /* return the global irq number corresponding to a given device irq
254 pin. We could also use the bus number to have a more precise
256 static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
259 slot_addend = (pci_dev->devfn >> 3) - 1;
260 return (irq_num + slot_addend) & 3;
264 copy_bios(PCIDevice *d, int v)
266 pci_config_writeb(d, 0x59, v);
267 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
270 // Test if 'addr' is in the range from 'start'..'start+size'
271 #define IN_RANGE(addr, start, size) ({ \
272 u32 __addr = (addr); \
273 u32 __start = (start); \
274 u32 __size = (size); \
275 (__addr - __start < __size); \
278 static void bios_shadow_init(PCIDevice *d)
280 bios_table_cur_addr = 0xf0000 | OFFSET_freespace2_start;
281 bios_table_end_addr = 0xf0000 | OFFSET_freespace2_end;
282 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
283 bios_table_cur_addr, bios_table_end_addr);
285 /* remap the BIOS to shadow RAM an keep it read/write while we
286 are writing tables */
287 int v = pci_config_readb(d, 0x59);
289 pci_config_writeb(d, 0x59, v);
290 memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
293 if (IN_RANGE((u32)copy_bios, 0xf0000, 0x10000)) {
294 // Current code is in shadowed area. Perform the copy from
295 // the code that is in the temporary location.
296 u32 pos = (u32)copy_bios - 0xf0000 + BIOS_TMP_STORAGE;
297 void (*func)(PCIDevice *, int) = (void*)pos;
303 // Clear the area just copied.
304 memcpy((void *)BIOS_TMP_STORAGE, 0, 0x10000);
309 static void bios_lock_shadow_ram(void)
311 PCIDevice *d = &i440_pcidev;
315 v = pci_config_readb(d, 0x59);
316 v = (v & 0x0f) | (0x10);
317 pci_config_writeb(d, 0x59, v);
320 static void pci_bios_init_bridges(PCIDevice *d)
322 u16 vendor_id, device_id;
324 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
325 device_id = pci_config_readw(d, PCI_DEVICE_ID);
327 if (vendor_id == 0x8086 && device_id == 0x7000) {
335 for(i = 0; i < 4; i++) {
337 /* set to trigger level */
338 elcr[irq >> 3] |= (1 << (irq & 7));
339 /* activate irq remapping in PIIX */
340 pci_config_writeb(d, 0x60 + i, irq);
342 outb(elcr[0], 0x4d0);
343 outb(elcr[1], 0x4d1);
344 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
346 } else if (vendor_id == 0x8086 && device_id == 0x1237) {
347 /* i440 PCI bridge */
353 ".globl smp_ap_boot_code_start\n"
354 ".globl smp_ap_boot_code_end\n"
355 ".global smm_relocation_start\n"
356 ".global smm_relocation_end\n"
357 ".global smm_code_start\n"
358 ".global smm_code_end\n"
361 "smp_ap_boot_code_start:\n"
364 " incw " __stringify(CPU_COUNT_ADDR) "\n"
368 "smp_ap_boot_code_end:\n"
370 /* code to relocate SMBASE to 0xa0000 */
371 "smm_relocation_start:\n"
372 " mov $0x38000 + 0x7efc, %ebx\n"
373 " addr32 mov (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */
376 " mov $0x38000 + 0x7ef8, %ebx\n"
379 " mov $0x38000 + 0x7f00, %ebx\n"
381 " movl $0xa0000, %eax\n"
382 " addr32 movl %eax, (%ebx)\n"
383 /* indicate to the BIOS that the SMM code was executed */
388 "smm_relocation_end:\n"
390 /* minimal SMM code to enable or disable ACPI */
398 " mov $" __stringify(PM_IO_BASE) " + 0x04, %dx\n" /* PMCNTRL */
410 " mov $" __stringify(PM_IO_BASE) " + 0x04, %dx\n" /* PMCNTRL */
421 extern u8 smm_relocation_start, smm_relocation_end;
422 extern u8 smm_code_start, smm_code_end;
425 static void smm_init(PCIDevice *d)
429 /* check if SMM init is already done */
430 value = pci_config_readl(d, 0x58);
431 if ((value & (1 << 25)) == 0) {
433 /* copy the SMM relocation code */
434 memcpy((void *)0x38000, &smm_relocation_start,
435 &smm_relocation_end - &smm_relocation_start);
437 /* enable SMI generation when writing to the APMC register */
438 pci_config_writel(d, 0x58, value | (1 << 25));
440 /* init APM status port */
443 /* raise an SMI interrupt */
446 /* wait until SMM code executed */
447 while (inb(0xb3) != 0x00);
449 /* enable the SMM memory window */
450 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
452 /* copy the SMM code */
453 memcpy((void *)0xa8000, &smm_code_start,
454 &smm_code_end - &smm_code_start);
457 /* close the SMM memory window and enable normal SMM */
458 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
463 static void pci_bios_init_device(PCIDevice *d)
467 int i, pin, pic_irq, vendor_id, device_id;
469 class = pci_config_readw(d, PCI_CLASS_DEVICE);
470 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
471 device_id = pci_config_readw(d, PCI_DEVICE_ID);
472 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
473 d->bus, d->devfn, vendor_id, device_id);
476 if (vendor_id == 0x8086 && device_id == 0x7010) {
478 pci_config_writew(d, 0x40, 0x8000); // enable IDE0
479 pci_config_writew(d, 0x42, 0x8000); // enable IDE1
482 /* IDE: we map it as in ISA mode */
483 pci_set_io_region_addr(d, 0, 0x1f0);
484 pci_set_io_region_addr(d, 1, 0x3f4);
485 pci_set_io_region_addr(d, 2, 0x170);
486 pci_set_io_region_addr(d, 3, 0x374);
490 if (vendor_id != 0x1234)
492 /* VGA: map frame buffer to default Bochs VBE address */
493 pci_set_io_region_addr(d, 0, 0xE0000000);
497 if (vendor_id == 0x1014) {
499 if (device_id == 0x0046 || device_id == 0xFFFF) {
501 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
506 if (vendor_id == 0x0106b &&
507 (device_id == 0x0017 || device_id == 0x0022)) {
509 pci_set_io_region_addr(d, 0, 0x80800000);
514 /* default memory mappings */
515 for(i = 0; i < PCI_NUM_REGIONS; i++) {
519 if (i == PCI_ROM_SLOT)
523 pci_config_writel(d, ofs, 0xffffffff);
524 val = pci_config_readl(d, ofs);
526 size = (~(val & ~0xf)) + 1;
527 if (val & PCI_ADDRESS_SPACE_IO)
528 paddr = &pci_bios_io_addr;
529 else if (size >= 0x04000000)
530 paddr = &pci_bios_bigmem_addr;
532 paddr = &pci_bios_mem_addr;
533 *paddr = (*paddr + size - 1) & ~(size - 1);
534 pci_set_io_region_addr(d, i, *paddr);
541 /* map the interrupt */
542 pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
544 pin = pci_slot_get_pirq(d, pin - 1);
545 pic_irq = pci_irqs[pin];
546 pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
549 if (vendor_id == 0x8086 && device_id == 0x7113) {
550 /* PIIX4 Power Management device (for ACPI) */
551 pm_io_base = PM_IO_BASE;
552 pci_config_writel(d, 0x40, pm_io_base | 1);
553 pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
554 smb_io_base = SMB_IO_BASE;
555 pci_config_writel(d, 0x90, smb_io_base | 1);
556 pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
557 pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE);
565 void pci_for_each_device(void (*init_func)(PCIDevice *d))
567 PCIDevice d1, *d = &d1;
569 u16 vendor_id, device_id;
571 for(bus = 0; bus < 1; bus++) {
572 for(devfn = 0; devfn < 256; devfn++) {
575 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
576 device_id = pci_config_readw(d, PCI_DEVICE_ID);
577 if (vendor_id != 0xffff || device_id != 0xffff) {
584 void pci_bios_init(void)
586 pci_bios_io_addr = 0xc000;
587 pci_bios_mem_addr = 0xf0000000;
588 pci_bios_bigmem_addr = ram_size;
589 if (pci_bios_bigmem_addr < 0x90000000)
590 pci_bios_bigmem_addr = 0x90000000;
592 pci_for_each_device(pci_bios_init_bridges);
594 pci_for_each_device(pci_bios_init_device);
597 /****************************************************/
598 /* Multi Processor table init */
600 static void putb(u8 **pp, int val)
608 static void putstr(u8 **pp, const char *str)
617 static void putle16(u8 **pp, int val)
626 static void putle32(u8 **pp, int val)
637 static int mpf_checksum(const u8 *data, int len)
641 for(i = 0; i < len; i++)
646 static unsigned long align(unsigned long addr, unsigned long v)
648 return (addr + v - 1) & ~(v - 1);
651 static void mptable_init(void)
653 u8 *mp_config_table, *q, *float_pointer_struct;
654 int ioapic_id, i, len;
655 int mp_config_table_size;
662 #ifdef BX_USE_EBDA_TABLES
663 mp_config_table = (u8 *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
665 bios_table_cur_addr = align(bios_table_cur_addr, 16);
666 mp_config_table = (u8 *)bios_table_cur_addr;
669 putstr(&q, "PCMP"); /* "PCMP signature */
670 putle16(&q, 0); /* table length (patched later) */
671 putb(&q, 4); /* spec rev */
672 putb(&q, 0); /* checksum (patched later) */
674 putstr(&q, "QEMUCPU "); /* OEM id */
676 putstr(&q, "BOCHSCPU");
678 putstr(&q, "0.1 "); /* vendor id */
679 putle32(&q, 0); /* OEM table ptr */
680 putle16(&q, 0); /* OEM table size */
681 putle16(&q, smp_cpus + 18); /* entry count */
682 putle32(&q, 0xfee00000); /* local APIC addr */
683 putle16(&q, 0); /* ext table length */
684 putb(&q, 0); /* ext table checksum */
685 putb(&q, 0); /* reserved */
687 for(i = 0; i < smp_cpus; i++) {
688 putb(&q, 0); /* entry type = processor */
689 putb(&q, i); /* APIC id */
690 putb(&q, 0x11); /* local APIC version number */
692 putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
694 putb(&q, 1); /* cpu flags: enabled */
695 putb(&q, 0); /* cpu signature */
699 putle16(&q, 0x201); /* feature flags */
702 putle16(&q, 0); /* reserved */
709 putb(&q, 1); /* entry type = bus */
710 putb(&q, 0); /* bus ID */
714 ioapic_id = smp_cpus;
715 putb(&q, 2); /* entry type = I/O APIC */
716 putb(&q, ioapic_id); /* apic ID */
717 putb(&q, 0x11); /* I/O APIC version number */
718 putb(&q, 1); /* enable */
719 putle32(&q, 0xfec00000); /* I/O APIC addr */
722 for(i = 0; i < 16; i++) {
723 putb(&q, 3); /* entry type = I/O interrupt */
724 putb(&q, 0); /* interrupt type = vectored interrupt */
725 putb(&q, 0); /* flags: po=0, el=0 */
727 putb(&q, 0); /* source bus ID = ISA */
728 putb(&q, i); /* source bus IRQ */
729 putb(&q, ioapic_id); /* dest I/O APIC ID */
730 putb(&q, i); /* dest I/O APIC interrupt in */
733 len = q - mp_config_table;
734 mp_config_table[4] = len;
735 mp_config_table[5] = len >> 8;
737 mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
739 mp_config_table_size = q - mp_config_table;
741 #ifndef BX_USE_EBDA_TABLES
742 bios_table_cur_addr += mp_config_table_size;
745 /* floating pointer structure */
746 #ifdef BX_USE_EBDA_TABLES
747 ebda_cur_addr = align(ebda_cur_addr, 16);
748 float_pointer_struct = (u8 *)ebda_cur_addr;
750 bios_table_cur_addr = align(bios_table_cur_addr, 16);
751 float_pointer_struct = (u8 *)bios_table_cur_addr;
753 q = float_pointer_struct;
755 /* pointer to MP config table */
756 putle32(&q, (unsigned long)mp_config_table);
758 putb(&q, 1); /* length in 16 byte units */
759 putb(&q, 4); /* MP spec revision */
760 putb(&q, 0); /* checksum (patched later) */
761 putb(&q, 0); /* MP feature byte 1 */
767 float_pointer_struct[10] =
768 -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
769 #ifdef BX_USE_EBDA_TABLES
770 ebda_cur_addr += (q - float_pointer_struct);
772 bios_table_cur_addr += (q - float_pointer_struct);
774 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
775 (unsigned long)float_pointer_struct,
776 (unsigned long)mp_config_table,
777 mp_config_table_size);
780 /****************************************************/
781 /* ACPI tables init */
783 /* Table structure from Linux kernel (the ACPI tables are under the
786 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
787 u8 signature [4]; /* ACPI signature (4 ASCII characters) */\
788 u32 length; /* Length of table, in bytes, including header */\
789 u8 revision; /* ACPI Specification minor version # */\
790 u8 checksum; /* To make sum of entire table == 0 */\
791 u8 oem_id [6]; /* OEM identification */\
792 u8 oem_table_id [8]; /* OEM table identification */\
793 u32 oem_revision; /* OEM revision number */\
794 u8 asl_compiler_id [4]; /* ASL compiler vendor ID */\
795 u32 asl_compiler_revision; /* ASL compiler revision number */
798 struct acpi_table_header /* ACPI common table header */
800 ACPI_TABLE_HEADER_DEF
803 struct rsdp_descriptor /* Root System Descriptor Pointer */
805 u8 signature [8]; /* ACPI signature, contains "RSD PTR " */
806 u8 checksum; /* To make sum of struct == 0 */
807 u8 oem_id [6]; /* OEM identification */
808 u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */
809 u32 rsdt_physical_address; /* 32-bit physical address of RSDT */
810 u32 length; /* XSDT Length in bytes including hdr */
811 u64 xsdt_physical_address; /* 64-bit physical address of XSDT */
812 u8 extended_checksum; /* Checksum of entire table */
813 u8 reserved [3]; /* Reserved field must be 0 */
817 * ACPI 1.0 Root System Description Table (RSDT)
819 struct rsdt_descriptor_rev1
821 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
822 u32 table_offset_entry [3]; /* Array of pointers to other */
827 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
829 struct facs_descriptor_rev1
831 u8 signature[4]; /* ACPI Signature */
832 u32 length; /* Length of structure, in bytes */
833 u32 hardware_signature; /* Hardware configuration signature */
834 u32 firmware_waking_vector; /* ACPI OS waking vector */
835 u32 global_lock; /* Global Lock */
836 u32 S4bios_f : 1; /* Indicates if S4BIOS support is present */
837 u32 reserved1 : 31; /* Must be 0 */
838 u8 resverved3 [40]; /* Reserved - must be zero */
843 * ACPI 1.0 Fixed ACPI Description Table (FADT)
845 struct fadt_descriptor_rev1
847 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
848 u32 firmware_ctrl; /* Physical address of FACS */
849 u32 dsdt; /* Physical address of DSDT */
850 u8 model; /* System Interrupt Model */
851 u8 reserved1; /* Reserved */
852 u16 sci_int; /* System vector of SCI interrupt */
853 u32 smi_cmd; /* Port address of SMI command port */
854 u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
855 u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
856 u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
857 u8 reserved2; /* Reserved - must be zero */
858 u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
859 u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
860 u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
861 u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
862 u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
863 u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
864 u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
865 u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
866 u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
867 u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
868 u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
869 u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
870 u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
871 u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
872 u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
873 u8 reserved3; /* Reserved */
874 u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
875 u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
876 u16 flush_size; /* Size of area read to flush caches */
877 u16 flush_stride; /* Stride used in flushing caches */
878 u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */
879 u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */
880 u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
881 u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
882 u8 century; /* Index to century in RTC CMOS RAM */
883 u8 reserved4; /* Reserved */
884 u8 reserved4a; /* Reserved */
885 u8 reserved4b; /* Reserved */
887 u32 wb_invd : 1; /* The wbinvd instruction works properly */
888 u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
889 u32 proc_c1 : 1; /* All processors support C1 state */
890 u32 plvl2_up : 1; /* C2 state works on MP system */
891 u32 pwr_button : 1; /* Power button is handled as a generic feature */
892 u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
893 u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
894 u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
895 u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
896 u32 reserved5 : 23; /* Reserved - must be zero */
903 * MADT values and structures
906 /* Values for MADT PCATCompat */
909 #define MULTIPLE_APIC 1
914 struct multiple_apic_table
916 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
917 u32 local_apic_address; /* Physical address of local APIC */
919 u32 PCATcompat : 1; /* A one indicates system also has dual 8259s */
927 /* Values for Type in APIC_HEADER_DEF */
929 #define APIC_PROCESSOR 0
931 #define APIC_XRUPT_OVERRIDE 2
933 #define APIC_LOCAL_NMI 4
934 #define APIC_ADDRESS_OVERRIDE 5
935 #define APIC_IO_SAPIC 6
936 #define APIC_LOCAL_SAPIC 7
937 #define APIC_XRUPT_SOURCE 8
938 #define APIC_RESERVED 9 /* 9 and greater are reserved */
941 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
943 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
947 /* Sub-structures for MADT */
949 struct madt_processor_apic
952 u8 processor_id; /* ACPI processor id */
953 u8 local_apic_id; /* Processor's local APIC id */
955 u32 processor_enabled: 1; /* Processor is usable if set */
956 u32 reserved2 : 31; /* Reserved, must be zero */
965 u8 io_apic_id; /* I/O APIC ID */
966 u8 reserved; /* Reserved - must be zero */
967 u32 address; /* APIC physical address */
968 u32 interrupt; /* Global system interrupt where INTI
972 #include "acpi-dsdt.hex"
974 static inline u16 cpu_to_le16(u16 x)
979 static inline u32 cpu_to_le32(u32 x)
984 static int acpi_checksum(const u8 *data, int len)
988 for(i = 0; i < len; i++)
990 return (-sum) & 0xff;
993 static void acpi_build_table_header(struct acpi_table_header *h,
994 char *sig, int len, u8 rev)
996 memcpy(h->signature, sig, 4);
997 h->length = cpu_to_le32(len);
1000 memcpy(h->oem_id, "QEMU ", 6);
1001 memcpy(h->oem_table_id, "QEMU", 4);
1003 memcpy(h->oem_id, "BOCHS ", 6);
1004 memcpy(h->oem_table_id, "BXPC", 4);
1006 memcpy(h->oem_table_id + 4, sig, 4);
1007 h->oem_revision = cpu_to_le32(1);
1009 memcpy(h->asl_compiler_id, "QEMU", 4);
1011 memcpy(h->asl_compiler_id, "BXPC", 4);
1013 h->asl_compiler_revision = cpu_to_le32(1);
1014 h->checksum = acpi_checksum((void *)h, len);
1017 int acpi_build_processor_ssdt(u8 *ssdt)
1019 u8 *ssdt_ptr = ssdt;
1021 int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus;
1023 ssdt_ptr[9] = 0; // checksum;
1024 ssdt_ptr += sizeof(struct acpi_table_header);
1026 // caluculate the length of processor block and scope block excluding PkgLength
1027 length = 0x0d * acpi_cpus + 4;
1029 // build processor scope header
1030 *(ssdt_ptr++) = 0x10; // ScopeOp
1031 if (length <= 0x3e) {
1032 *(ssdt_ptr++) = length + 1;
1034 *(ssdt_ptr++) = 0x7F;
1035 *(ssdt_ptr++) = (length + 2) >> 6;
1037 *(ssdt_ptr++) = '_'; // Name
1038 *(ssdt_ptr++) = 'P';
1039 *(ssdt_ptr++) = 'R';
1040 *(ssdt_ptr++) = '_';
1042 // build object for each processor
1043 for(i=0;i<acpi_cpus;i++) {
1044 *(ssdt_ptr++) = 0x5B; // ProcessorOp
1045 *(ssdt_ptr++) = 0x83;
1046 *(ssdt_ptr++) = 0x0B; // Length
1047 *(ssdt_ptr++) = 'C'; // Name (CPUxx)
1048 *(ssdt_ptr++) = 'P';
1049 if ((i & 0xf0) != 0)
1050 *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
1052 *(ssdt_ptr++) = 'U';
1053 *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
1055 *(ssdt_ptr++) = 0x10; // Processor block address
1056 *(ssdt_ptr++) = 0xb0;
1059 *(ssdt_ptr++) = 6; // Processor block length
1062 acpi_build_table_header((struct acpi_table_header *)ssdt,
1063 "SSDT", ssdt_ptr - ssdt, 1);
1065 return ssdt_ptr - ssdt;
1068 /* base_addr must be a multiple of 4KB */
1069 void acpi_bios_init(void)
1071 struct rsdp_descriptor *rsdp;
1072 struct rsdt_descriptor_rev1 *rsdt;
1073 struct fadt_descriptor_rev1 *fadt;
1074 struct facs_descriptor_rev1 *facs;
1075 struct multiple_apic_table *madt;
1077 u32 base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
1078 u32 acpi_tables_size, madt_addr, madt_size;
1081 /* reserve memory space for tables */
1082 #ifdef BX_USE_EBDA_TABLES
1083 ebda_cur_addr = align(ebda_cur_addr, 16);
1084 rsdp = (void *)(ebda_cur_addr);
1085 ebda_cur_addr += sizeof(*rsdp);
1087 bios_table_cur_addr = align(bios_table_cur_addr, 16);
1088 rsdp = (void *)(bios_table_cur_addr);
1089 bios_table_cur_addr += sizeof(*rsdp);
1092 addr = base_addr = ram_size - ACPI_DATA_SIZE;
1094 rsdt = (void *)(addr);
1095 addr += sizeof(*rsdt);
1098 fadt = (void *)(addr);
1099 addr += sizeof(*fadt);
1101 /* XXX: FACS should be in RAM */
1102 addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
1104 facs = (void *)(addr);
1105 addr += sizeof(*facs);
1108 dsdt = (void *)(addr);
1109 addr += sizeof(AmlCode);
1112 ssdt = (void *)(addr);
1113 addr += acpi_build_processor_ssdt(ssdt);
1115 addr = (addr + 7) & ~7;
1117 madt_size = sizeof(*madt) +
1118 sizeof(struct madt_processor_apic) * smp_cpus +
1119 sizeof(struct madt_io_apic);
1120 madt = (void *)(addr);
1123 acpi_tables_size = addr - base_addr;
1125 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1126 (unsigned long)rsdp,
1127 (unsigned long)rsdt, acpi_tables_size);
1130 memset(rsdp, 0, sizeof(*rsdp));
1131 memcpy(rsdp->signature, "RSD PTR ", 8);
1133 memcpy(rsdp->oem_id, "QEMU ", 6);
1135 memcpy(rsdp->oem_id, "BOCHS ", 6);
1137 rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
1138 rsdp->checksum = acpi_checksum((void *)rsdp, 20);
1141 memset(rsdt, 0, sizeof(*rsdt));
1142 rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
1143 rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
1144 rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
1145 acpi_build_table_header((struct acpi_table_header *)rsdt,
1146 "RSDT", sizeof(*rsdt), 1);
1149 memset(fadt, 0, sizeof(*fadt));
1150 fadt->firmware_ctrl = cpu_to_le32(facs_addr);
1151 fadt->dsdt = cpu_to_le32(dsdt_addr);
1153 fadt->reserved1 = 0;
1154 fadt->sci_int = cpu_to_le16(pm_sci_int);
1155 fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
1156 fadt->acpi_enable = 0xf1;
1157 fadt->acpi_disable = 0xf0;
1158 fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
1159 fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
1160 fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
1161 fadt->pm1_evt_len = 4;
1162 fadt->pm1_cnt_len = 2;
1163 fadt->pm_tmr_len = 4;
1164 fadt->plvl2_lat = cpu_to_le16(50);
1165 fadt->plvl3_lat = cpu_to_le16(50);
1166 fadt->plvl3_lat = cpu_to_le16(50);
1167 /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
1168 fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
1169 acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
1173 memset(facs, 0, sizeof(*facs));
1174 memcpy(facs->signature, "FACS", 4);
1175 facs->length = cpu_to_le32(sizeof(*facs));
1178 memcpy(dsdt, AmlCode, sizeof(AmlCode));
1182 struct madt_processor_apic *apic;
1183 struct madt_io_apic *io_apic;
1185 memset(madt, 0, madt_size);
1186 madt->local_apic_address = cpu_to_le32(0xfee00000);
1187 madt->flags = cpu_to_le32(1);
1188 apic = (void *)(madt + 1);
1189 for(i=0;i<smp_cpus;i++) {
1190 apic->type = APIC_PROCESSOR;
1191 apic->length = sizeof(*apic);
1192 apic->processor_id = i;
1193 apic->local_apic_id = i;
1194 apic->flags = cpu_to_le32(1);
1197 io_apic = (void *)apic;
1198 io_apic->type = APIC_IO;
1199 io_apic->length = sizeof(*io_apic);
1200 io_apic->io_apic_id = smp_cpus;
1201 io_apic->address = cpu_to_le32(0xfec00000);
1202 io_apic->interrupt = cpu_to_le32(0);
1204 acpi_build_table_header((struct acpi_table_header *)madt,
1205 "APIC", madt_size, 1);
1209 /* SMBIOS entry point -- must be written to a 16-bit aligned address
1210 between 0xf0000 and 0xfffff.
1212 struct smbios_entry_point {
1213 char anchor_string[4];
1216 u8 smbios_major_version;
1217 u8 smbios_minor_version;
1218 u16 max_structure_size;
1219 u8 entry_point_revision;
1220 u8 formatted_area[5];
1221 char intermediate_anchor_string[5];
1222 u8 intermediate_checksum;
1223 u16 structure_table_length;
1224 u32 structure_table_address;
1225 u16 number_of_structures;
1226 u8 smbios_bcd_revision;
1227 } __attribute__((__packed__));
1229 /* This goes at the beginning of every SMBIOS structure. */
1230 struct smbios_structure_header {
1234 } __attribute__((__packed__));
1236 /* SMBIOS type 0 - BIOS Information */
1237 struct smbios_type_0 {
1238 struct smbios_structure_header header;
1240 u8 bios_version_str;
1241 u16 bios_starting_address_segment;
1242 u8 bios_release_date_str;
1244 u8 bios_characteristics[8];
1245 u8 bios_characteristics_extension_bytes[2];
1246 u8 system_bios_major_release;
1247 u8 system_bios_minor_release;
1248 u8 embedded_controller_major_release;
1249 u8 embedded_controller_minor_release;
1250 } __attribute__((__packed__));
1252 /* SMBIOS type 1 - System Information */
1253 struct smbios_type_1 {
1254 struct smbios_structure_header header;
1255 u8 manufacturer_str;
1256 u8 product_name_str;
1258 u8 serial_number_str;
1263 } __attribute__((__packed__));
1265 /* SMBIOS type 3 - System Enclosure (v2.3) */
1266 struct smbios_type_3 {
1267 struct smbios_structure_header header;
1268 u8 manufacturer_str;
1271 u8 serial_number_str;
1272 u8 asset_tag_number_str;
1274 u8 power_supply_state;
1279 u8 number_of_power_cords;
1280 u8 contained_element_count;
1281 // contained elements follow
1282 } __attribute__((__packed__));
1284 /* SMBIOS type 4 - Processor Information (v2.0) */
1285 struct smbios_type_4 {
1286 struct smbios_structure_header header;
1287 u8 socket_designation_str;
1289 u8 processor_family;
1290 u8 processor_manufacturer_str;
1291 u32 processor_id[2];
1292 u8 processor_version_str;
1298 u8 processor_upgrade;
1299 } __attribute__((__packed__));
1301 /* SMBIOS type 16 - Physical Memory Array
1302 * Associated with one type 17 (Memory Device).
1304 struct smbios_type_16 {
1305 struct smbios_structure_header header;
1308 u8 error_correction;
1309 u32 maximum_capacity;
1310 u16 memory_error_information_handle;
1311 u16 number_of_memory_devices;
1312 } __attribute__((__packed__));
1314 /* SMBIOS type 17 - Memory Device
1315 * Associated with one type 19
1317 struct smbios_type_17 {
1318 struct smbios_structure_header header;
1319 u16 physical_memory_array_handle;
1320 u16 memory_error_information_handle;
1326 u8 device_locator_str;
1327 u8 bank_locator_str;
1330 } __attribute__((__packed__));
1332 /* SMBIOS type 19 - Memory Array Mapped Address */
1333 struct smbios_type_19 {
1334 struct smbios_structure_header header;
1335 u32 starting_address;
1337 u16 memory_array_handle;
1339 } __attribute__((__packed__));
1341 /* SMBIOS type 20 - Memory Device Mapped Address */
1342 struct smbios_type_20 {
1343 struct smbios_structure_header header;
1344 u32 starting_address;
1346 u16 memory_device_handle;
1347 u16 memory_array_mapped_address_handle;
1348 u8 partition_row_position;
1349 u8 interleave_position;
1350 u8 interleaved_data_depth;
1351 } __attribute__((__packed__));
1353 /* SMBIOS type 32 - System Boot Information */
1354 struct smbios_type_32 {
1355 struct smbios_structure_header header;
1358 } __attribute__((__packed__));
1360 /* SMBIOS type 127 -- End-of-table */
1361 struct smbios_type_127 {
1362 struct smbios_structure_header header;
1363 } __attribute__((__packed__));
1366 smbios_entry_point_init(void *start,
1367 u16 max_structure_size,
1368 u16 structure_table_length,
1369 u32 structure_table_address,
1370 u16 number_of_structures)
1374 struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
1376 memcpy(ep->anchor_string, "_SM_", 4);
1378 ep->smbios_major_version = 2;
1379 ep->smbios_minor_version = 4;
1380 ep->max_structure_size = max_structure_size;
1381 ep->entry_point_revision = 0;
1382 memset(ep->formatted_area, 0, 5);
1383 memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
1385 ep->structure_table_length = structure_table_length;
1386 ep->structure_table_address = structure_table_address;
1387 ep->number_of_structures = number_of_structures;
1388 ep->smbios_bcd_revision = 0x24;
1391 ep->intermediate_checksum = 0;
1394 for (i = 0; i < 0x10; i++)
1395 sum += ((s8 *)start)[i];
1396 ep->checksum = -sum;
1399 for (i = 0x10; i < ep->length; i++)
1400 sum += ((s8 *)start)[i];
1401 ep->intermediate_checksum = -sum;
1404 /* Type 0 -- BIOS Information */
1405 #define RELEASE_DATE_STR "01/01/2007"
1407 smbios_type_0_init(void *start)
1409 struct smbios_type_0 *p = (struct smbios_type_0 *)start;
1412 p->header.length = sizeof(struct smbios_type_0);
1413 p->header.handle = 0;
1416 p->bios_version_str = 1;
1417 p->bios_starting_address_segment = 0xe800;
1418 p->bios_release_date_str = 2;
1419 p->bios_rom_size = 0; /* FIXME */
1421 memset(p->bios_characteristics, 0, 7);
1422 p->bios_characteristics[7] = 0x08; /* BIOS characteristics not supported */
1423 p->bios_characteristics_extension_bytes[0] = 0;
1424 p->bios_characteristics_extension_bytes[1] = 0;
1426 p->system_bios_major_release = 1;
1427 p->system_bios_minor_release = 0;
1428 p->embedded_controller_major_release = 0xff;
1429 p->embedded_controller_minor_release = 0xff;
1431 start += sizeof(struct smbios_type_0);
1432 memcpy((char *)start, BX_APPNAME, sizeof(BX_APPNAME));
1433 start += sizeof(BX_APPNAME);
1434 memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR));
1435 start += sizeof(RELEASE_DATE_STR);
1441 /* Type 1 -- System Information */
1443 smbios_type_1_init(void *start)
1445 struct smbios_type_1 *p = (struct smbios_type_1 *)start;
1447 p->header.length = sizeof(struct smbios_type_1);
1448 p->header.handle = 0x100;
1450 p->manufacturer_str = 0;
1451 p->product_name_str = 0;
1453 p->serial_number_str = 0;
1455 memcpy(p->uuid, bios_uuid, 16);
1457 p->wake_up_type = 0x06; /* power switch */
1458 p->sku_number_str = 0;
1461 start += sizeof(struct smbios_type_1);
1462 *((u16 *)start) = 0;
1467 /* Type 3 -- System Enclosure */
1469 smbios_type_3_init(void *start)
1471 struct smbios_type_3 *p = (struct smbios_type_3 *)start;
1474 p->header.length = sizeof(struct smbios_type_3);
1475 p->header.handle = 0x300;
1477 p->manufacturer_str = 0;
1478 p->type = 0x01; /* other */
1480 p->serial_number_str = 0;
1481 p->asset_tag_number_str = 0;
1482 p->boot_up_state = 0x03; /* safe */
1483 p->power_supply_state = 0x03; /* safe */
1484 p->thermal_state = 0x03; /* safe */
1485 p->security_status = 0x02; /* unknown */
1488 p->number_of_power_cords = 0;
1489 p->contained_element_count = 0;
1491 start += sizeof(struct smbios_type_3);
1492 *((u16 *)start) = 0;
1497 /* Type 4 -- Processor Information */
1499 smbios_type_4_init(void *start, unsigned int cpu_number)
1501 struct smbios_type_4 *p = (struct smbios_type_4 *)start;
1504 p->header.length = sizeof(struct smbios_type_4);
1505 p->header.handle = 0x400 + cpu_number;
1507 p->socket_designation_str = 1;
1508 p->processor_type = 0x03; /* CPU */
1509 p->processor_family = 0x01; /* other */
1510 p->processor_manufacturer_str = 0;
1512 p->processor_id[0] = cpuid_signature;
1513 p->processor_id[1] = cpuid_features;
1515 p->processor_version_str = 0;
1517 p->external_clock = 0;
1519 p->max_speed = 0; /* unknown */
1520 p->current_speed = 0; /* unknown */
1522 p->status = 0x41; /* socket populated, CPU enabled */
1523 p->processor_upgrade = 0x01; /* other */
1525 start += sizeof(struct smbios_type_4);
1527 memcpy((char *)start, "CPU " "\0" "" "\0" "", 7);
1528 ((char *)start)[4] = cpu_number + '0';
1533 /* Type 16 -- Physical Memory Array */
1535 smbios_type_16_init(void *start, u32 memsize)
1537 struct smbios_type_16 *p = (struct smbios_type_16*)start;
1539 p->header.type = 16;
1540 p->header.length = sizeof(struct smbios_type_16);
1541 p->header.handle = 0x1000;
1543 p->location = 0x01; /* other */
1544 p->use = 0x03; /* system memory */
1545 p->error_correction = 0x01; /* other */
1546 p->maximum_capacity = memsize * 1024;
1547 p->memory_error_information_handle = 0xfffe; /* none provided */
1548 p->number_of_memory_devices = 1;
1550 start += sizeof(struct smbios_type_16);
1551 *((u16 *)start) = 0;
1556 /* Type 17 -- Memory Device */
1558 smbios_type_17_init(void *start, u32 memory_size_mb)
1560 struct smbios_type_17 *p = (struct smbios_type_17 *)start;
1562 p->header.type = 17;
1563 p->header.length = sizeof(struct smbios_type_17);
1564 p->header.handle = 0x1100;
1566 p->physical_memory_array_handle = 0x1000;
1567 p->total_width = 64;
1569 /* truncate memory_size_mb to 16 bits and clear most significant
1570 bit [indicates size in MB] */
1571 p->size = (u16) memory_size_mb & 0x7fff;
1572 p->form_factor = 0x09; /* DIMM */
1574 p->device_locator_str = 1;
1575 p->bank_locator_str = 0;
1576 p->memory_type = 0x07; /* RAM */
1579 start += sizeof(struct smbios_type_17);
1580 memcpy((char *)start, "DIMM 1", 7);
1587 /* Type 19 -- Memory Array Mapped Address */
1589 smbios_type_19_init(void *start, u32 memory_size_mb)
1591 struct smbios_type_19 *p = (struct smbios_type_19 *)start;
1593 p->header.type = 19;
1594 p->header.length = sizeof(struct smbios_type_19);
1595 p->header.handle = 0x1300;
1597 p->starting_address = 0;
1598 p->ending_address = (memory_size_mb-1) * 1024;
1599 p->memory_array_handle = 0x1000;
1600 p->partition_width = 1;
1602 start += sizeof(struct smbios_type_19);
1603 *((u16 *)start) = 0;
1608 /* Type 20 -- Memory Device Mapped Address */
1610 smbios_type_20_init(void *start, u32 memory_size_mb)
1612 struct smbios_type_20 *p = (struct smbios_type_20 *)start;
1614 p->header.type = 20;
1615 p->header.length = sizeof(struct smbios_type_20);
1616 p->header.handle = 0x1400;
1618 p->starting_address = 0;
1619 p->ending_address = (memory_size_mb-1)*1024;
1620 p->memory_device_handle = 0x1100;
1621 p->memory_array_mapped_address_handle = 0x1300;
1622 p->partition_row_position = 1;
1623 p->interleave_position = 0;
1624 p->interleaved_data_depth = 0;
1626 start += sizeof(struct smbios_type_20);
1628 *((u16 *)start) = 0;
1632 /* Type 32 -- System Boot Information */
1634 smbios_type_32_init(void *start)
1636 struct smbios_type_32 *p = (struct smbios_type_32 *)start;
1638 p->header.type = 32;
1639 p->header.length = sizeof(struct smbios_type_32);
1640 p->header.handle = 0x2000;
1641 memset(p->reserved, 0, 6);
1642 p->boot_status = 0; /* no errors detected */
1644 start += sizeof(struct smbios_type_32);
1645 *((u16 *)start) = 0;
1650 /* Type 127 -- End of Table */
1652 smbios_type_127_init(void *start)
1654 struct smbios_type_127 *p = (struct smbios_type_127 *)start;
1656 p->header.type = 127;
1657 p->header.length = sizeof(struct smbios_type_127);
1658 p->header.handle = 0x7f00;
1660 start += sizeof(struct smbios_type_127);
1661 *((u16 *)start) = 0;
1666 void smbios_init(void)
1668 unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
1669 char *start, *p, *q;
1670 int memsize = ram_size / (1024 * 1024);
1672 #ifdef BX_USE_EBDA_TABLES
1673 ebda_cur_addr = align(ebda_cur_addr, 16);
1674 start = (void *)(ebda_cur_addr);
1676 bios_table_cur_addr = align(bios_table_cur_addr, 16);
1677 start = (void *)(bios_table_cur_addr);
1680 p = (char *)start + sizeof(struct smbios_entry_point);
1682 #define add_struct(fn) { \
1685 if ((q - p) > max_struct_size) \
1686 max_struct_size = q - p; \
1690 add_struct(smbios_type_0_init(p));
1691 add_struct(smbios_type_1_init(p));
1692 add_struct(smbios_type_3_init(p));
1693 for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
1694 add_struct(smbios_type_4_init(p, cpu_num));
1695 add_struct(smbios_type_16_init(p, memsize));
1696 add_struct(smbios_type_17_init(p, memsize));
1697 add_struct(smbios_type_19_init(p, memsize));
1698 add_struct(smbios_type_20_init(p, memsize));
1699 add_struct(smbios_type_32_init(p));
1700 add_struct(smbios_type_127_init(p));
1704 smbios_entry_point_init(
1705 start, max_struct_size,
1706 (p - (char *)start) - sizeof(struct smbios_entry_point),
1707 (u32)(start + sizeof(struct smbios_entry_point)),
1710 #ifdef BX_USE_EBDA_TABLES
1711 ebda_cur_addr += (p - (char *)start);
1713 bios_table_cur_addr += (p - (char *)start);
1716 BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start);
1719 void rombios32_init(void)
1721 BX_INFO("Starting rombios32\n");
1733 if (bios_table_cur_addr != 0) {
1742 bios_lock_shadow_ram();
1744 BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr);
1745 if (bios_table_cur_addr > bios_table_end_addr)
1746 BX_PANIC("bios_table_end_addr overflow!\n");