1 /////////////////////////////////////////////////////////////////////////
2 // $Id: rombios32.c,v 1.11 2007/08/03 13:56:13 vruppert 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
26 typedef signed char int8_t;
27 typedef short int16_t;
29 typedef long long int64_t;
30 typedef unsigned char uint8_t;
31 typedef unsigned short uint16_t;
32 typedef unsigned int uint32_t;
33 typedef unsigned long long uint64_t;
35 /* if true, put the MP float table and ACPI RSDT in EBDA and the MP
36 table in RAM. Unfortunately, Linux has bugs with that, so we prefer
37 to modify the BIOS in shadow RAM */
38 //#define BX_USE_EBDA_TABLES
40 /* define it if the (emulated) hardware supports SMM mode */
43 #define cpuid(index, eax, ebx, ecx, edx) \
44 asm volatile ("cpuid" \
45 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
48 #define wbinvd() asm volatile("wbinvd")
50 #define CPUID_APIC (1 << 9)
52 #define APIC_BASE ((uint8_t *)0xfee00000)
53 #define APIC_ICR_LOW 0x300
54 #define APIC_SVR 0x0F0
56 #define APIC_LVT3 0x370
59 #define PCI_ISA_IRQ_MASK 0x0e20U
61 #define APIC_ENABLED 0x0100
63 #define AP_BOOT_ADDR 0x10000
65 #define MPTABLE_MAX_SIZE 0x00002000
66 #define SMI_CMD_IO_ADDR 0xb2
68 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
70 static inline void outl(int addr
, int val
)
72 asm volatile ("outl %1, %w0" : : "d" (addr
), "a" (val
));
75 static inline void outw(int addr
, int val
)
77 asm volatile ("outw %w1, %w0" : : "d" (addr
), "a" (val
));
80 static inline void outb(int addr
, int val
)
82 asm volatile ("outb %b1, %w0" : : "d" (addr
), "a" (val
));
85 static inline uint32_t inl(int addr
)
88 asm volatile ("inl %w1, %0" : "=a" (val
) : "d" (addr
));
92 static inline uint16_t inw(int addr
)
95 asm volatile ("inw %w1, %w0" : "=a" (val
) : "d" (addr
));
99 static inline uint8_t inb(int addr
)
102 asm volatile ("inb %w1, %b0" : "=a" (val
) : "d" (addr
));
106 static inline void writel(void *addr
, uint32_t val
)
108 *(volatile uint32_t *)addr
= val
;
111 static inline void writew(void *addr
, uint16_t val
)
113 *(volatile uint16_t *)addr
= val
;
116 static inline void writeb(void *addr
, uint8_t val
)
118 *(volatile uint8_t *)addr
= val
;
121 static inline uint32_t readl(const void *addr
)
123 return *(volatile const uint32_t *)addr
;
126 static inline uint16_t readw(const void *addr
)
128 return *(volatile const uint16_t *)addr
;
131 static inline uint8_t readb(const void *addr
)
133 return *(volatile const uint8_t *)addr
;
136 static inline void putc(int c
)
141 static inline int isdigit(int c
)
143 return c
>= '0' && c
<= '9';
146 void *memset(void *d1
, int val
, size_t len
)
156 void *memcpy(void *d1
, const void *s1
, size_t len
)
159 const uint8_t *s
= s1
;
167 void *memmove(void *d1
, const void *s1
, size_t len
)
170 const uint8_t *s
= s1
;
186 size_t strlen(const char *s
)
189 for(s1
= s
; *s1
!= '\0'; s1
++);
193 /* from BSD ppp sources */
194 int vsnprintf(char *buf
, int buflen
, const char *fmt
, va_list args
)
197 int width
, prec
, fillch
;
199 unsigned long val
= 0;
203 static const char hexchars
[] = "0123456789abcdef";
208 for (f
= fmt
; *f
!= '%' && *f
!= 0; ++f
)
214 memcpy(buf
, fmt
, len
);
229 width
= va_arg(args
, int);
233 width
= width
* 10 + c
- '0';
240 prec
= va_arg(args
, int);
244 prec
= prec
* 10 + c
- '0';
263 i
= va_arg(args
, int);
272 val
= va_arg(args
, unsigned int);
277 val
= va_arg(args
, unsigned int);
281 val
= (unsigned long) va_arg(args
, void *);
286 str
= va_arg(args
, char *);
289 num
[0] = va_arg(args
, int);
296 --fmt
; /* so %z outputs %z etc. */
301 str
= num
+ sizeof(num
);
303 while (str
> num
+ neg
) {
304 *--str
= hexchars
[val
% base
];
306 if (--prec
<= 0 && val
== 0)
318 len
= num
+ sizeof(num
) - 1 - str
;
321 if (prec
> 0 && len
> prec
)
327 if ((n
= width
- len
) > 0) {
335 memcpy(buf
, str
, len
);
343 void bios_printf(int flags
, const char *fmt
, ...)
350 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
360 for(i
= 0; i
< n
; i
++) {
362 /* approximative ! */
363 for(j
= 0; j
< 1000000; j
++);
368 r1
= inb(0x61) & 0x10;
370 r2
= inb(0x61) & 0x10;
382 uint32_t cpuid_features
;
383 uint32_t cpuid_ext_features
;
384 unsigned long ram_size
;
385 #ifdef BX_USE_EBDA_TABLES
386 unsigned long ebda_cur_addr
;
389 uint32_t pm_io_base
, smb_io_base
;
391 unsigned long bios_table_cur_addr
;
392 unsigned long bios_table_end_addr
;
396 uint32_t eax
, ebx
, ecx
, edx
;
397 cpuid(1, eax
, ebx
, ecx
, edx
);
398 cpuid_features
= edx
;
399 cpuid_ext_features
= ecx
;
402 static int cmos_readb(int addr
)
410 ram_size
= (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
412 #ifdef BX_USE_EBDA_TABLES
413 ebda_cur_addr
= ((*(uint16_t *)(0x40e)) << 4) + 0x380;
415 BX_INFO("ram_size=0x%08lx\n");
418 /****************************************************/
421 extern uint8_t smp_ap_boot_code_start
;
422 extern uint8_t smp_ap_boot_code_end
;
424 /* find the number of CPUs by launching a SIPI to them */
427 uint32_t val
, sipi_vector
;
430 if (cpuid_features
& CPUID_APIC
) {
432 /* enable local APIC */
433 val
= readl(APIC_BASE
+ APIC_SVR
);
435 writel(APIC_BASE
+ APIC_SVR
, val
);
437 writew((void *)CPU_COUNT_ADDR
, 1);
438 /* copy AP boot code */
439 memcpy((void *)AP_BOOT_ADDR
, &smp_ap_boot_code_start
,
440 &smp_ap_boot_code_end
- &smp_ap_boot_code_start
);
443 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4500);
444 sipi_vector
= AP_BOOT_ADDR
>> 12;
445 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4600 | sipi_vector
);
447 "xor %%eax, %%eax \n\t"
448 "xor %%edx, %%edx \n\t"
449 "mov $0x10, %%ecx \n\t"
451 : : : "eax", "ecx", "edx");
456 while (cmos_readb(0x5f) + 1 != readw((void *)CPU_COUNT_ADDR
))
460 smp_cpus
= readw((void *)CPU_COUNT_ADDR
);
462 BX_INFO("Found %d cpu(s)\n", smp_cpus
);
465 /****************************************************/
468 #define PCI_ADDRESS_SPACE_MEM 0x00
469 #define PCI_ADDRESS_SPACE_IO 0x01
470 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
472 #define PCI_ROM_SLOT 6
473 #define PCI_NUM_REGIONS 7
475 #define PCI_DEVICES_MAX 64
477 #define PCI_VENDOR_ID 0x00 /* 16 bits */
478 #define PCI_DEVICE_ID 0x02 /* 16 bits */
479 #define PCI_COMMAND 0x04 /* 16 bits */
480 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
481 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
482 #define PCI_CLASS_DEVICE 0x0a /* Device class */
483 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
484 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
485 #define PCI_MIN_GNT 0x3e /* 8 bits */
486 #define PCI_MAX_LAT 0x3f /* 8 bits */
488 typedef struct PCIDevice
{
493 static uint32_t pci_bios_io_addr
;
494 static uint32_t pci_bios_mem_addr
;
495 static uint32_t pci_bios_bigmem_addr
;
496 /* host irqs corresponding to PCI irqs A-D */
497 static uint8_t pci_irqs
[4] = { 10, 10, 11, 11 };
498 static PCIDevice i440_pcidev
;
500 static void pci_config_writel(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
502 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
506 static void pci_config_writew(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
508 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
509 outw(0xcfc + (addr
& 2), val
);
512 static void pci_config_writeb(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
514 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
515 outb(0xcfc + (addr
& 3), val
);
518 static uint32_t pci_config_readl(PCIDevice
*d
, uint32_t addr
)
520 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
524 static uint32_t pci_config_readw(PCIDevice
*d
, uint32_t addr
)
526 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
527 return inw(0xcfc + (addr
& 2));
530 static uint32_t pci_config_readb(PCIDevice
*d
, uint32_t addr
)
532 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
533 return inb(0xcfc + (addr
& 3));
536 static void pci_set_io_region_addr(PCIDevice
*d
, int region_num
, uint32_t addr
)
539 uint32_t ofs
, old_addr
;
541 if ( region_num
== PCI_ROM_SLOT
) {
544 ofs
= 0x10 + region_num
* 4;
547 old_addr
= pci_config_readl(d
, ofs
);
549 pci_config_writel(d
, ofs
, addr
);
550 BX_INFO("region %d: 0x%08x\n", region_num
, addr
);
552 /* enable memory mappings */
553 cmd
= pci_config_readw(d
, PCI_COMMAND
);
554 if ( region_num
== PCI_ROM_SLOT
)
556 else if (old_addr
& PCI_ADDRESS_SPACE_IO
)
560 pci_config_writew(d
, PCI_COMMAND
, cmd
);
563 /* return the global irq number corresponding to a given device irq
564 pin. We could also use the bus number to have a more precise
566 static int pci_slot_get_pirq(PCIDevice
*pci_dev
, int irq_num
)
569 slot_addend
= (pci_dev
->devfn
>> 3) - 1;
570 return (irq_num
+ slot_addend
) & 3;
573 static int find_bios_table_area(void)
576 for(addr
= 0xf0000; addr
< 0x100000; addr
+= 16) {
577 if (*(uint32_t *)addr
== 0xaafb4442) {
578 bios_table_cur_addr
= addr
+ 8;
579 bios_table_end_addr
= bios_table_cur_addr
+ *(uint32_t *)(addr
+ 4);
580 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
581 bios_table_cur_addr
, bios_table_end_addr
);
588 static void bios_shadow_init(PCIDevice
*d
)
592 if (find_bios_table_area() < 0)
595 /* remap the BIOS to shadow RAM an keep it read/write while we
596 are writing tables */
597 memcpy((void *)BIOS_TMP_STORAGE
, (void *)0x000f0000, 0x10000);
598 v
= pci_config_readb(d
, 0x59);
599 v
= (v
& 0x0f) | (0x30);
600 pci_config_writeb(d
, 0x59, v
);
601 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE
, 0x10000);
606 static void bios_lock_shadow_ram(void)
608 PCIDevice
*d
= &i440_pcidev
;
612 v
= pci_config_readb(d
, 0x59);
613 v
= (v
& 0x0f) | (0x10);
614 pci_config_writeb(d
, 0x59, v
);
617 static void pci_bios_init_bridges(PCIDevice
*d
)
619 uint16_t vendor_id
, device_id
;
621 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
622 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
624 if (vendor_id
== 0x8086 && device_id
== 0x7000) {
632 for(i
= 0; i
< 4; i
++) {
634 /* set to trigger level */
635 elcr
[irq
>> 3] |= (1 << (irq
& 7));
636 /* activate irq remapping in PIIX */
637 pci_config_writeb(d
, 0x60 + i
, irq
);
639 outb(0x4d0, elcr
[0]);
640 outb(0x4d1, elcr
[1]);
641 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
643 } else if (vendor_id
== 0x8086 && device_id
== 0x1237) {
644 /* i440 PCI bridge */
649 extern uint8_t smm_relocation_start
, smm_relocation_end
;
650 extern uint8_t smm_code_start
, smm_code_end
;
653 static void smm_init(PCIDevice
*d
)
655 /* copy the SMM relocation code */
656 memcpy((void *)0x38000, &smm_relocation_start
,
657 &smm_relocation_end
- &smm_relocation_start
);
659 /* enable SMI generation when writing to the APMC register */
660 pci_config_writel(d
, 0x58, pci_config_readl(d
, 0x58) | (1 << 25));
662 /* init APM status port */
665 /* raise an SMI interrupt */
668 /* wait until SMM code executed */
669 while (inb(0xb3) != 0x00);
671 /* enable the SMM memory window */
672 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x48);
674 /* copy the SMM code */
675 memcpy((void *)0xa8000, &smm_code_start
,
676 &smm_code_end
- &smm_code_start
);
679 /* close the SMM memory window and enable normal SMM */
680 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x08);
684 static void pci_bios_init_device(PCIDevice
*d
)
688 int i
, pin
, pic_irq
, vendor_id
, device_id
;
690 class = pci_config_readw(d
, PCI_CLASS_DEVICE
);
691 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
692 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
693 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
694 d
->bus
, d
->devfn
, vendor_id
, device_id
);
697 if (vendor_id
== 0x8086 && device_id
== 0x7010) {
699 pci_config_writew(d
, 0x40, 0x8000); // enable IDE0
700 pci_config_writew(d
, 0x42, 0x8000); // enable IDE1
703 /* IDE: we map it as in ISA mode */
704 pci_set_io_region_addr(d
, 0, 0x1f0);
705 pci_set_io_region_addr(d
, 1, 0x3f4);
706 pci_set_io_region_addr(d
, 2, 0x170);
707 pci_set_io_region_addr(d
, 3, 0x374);
711 if (vendor_id
!= 0x1234)
713 /* VGA: map frame buffer to default Bochs VBE address */
714 pci_set_io_region_addr(d
, 0, 0xE0000000);
718 if (vendor_id
== 0x1014) {
720 if (device_id
== 0x0046 || device_id
== 0xFFFF) {
722 pci_set_io_region_addr(d
, 0, 0x80800000 + 0x00040000);
727 if (vendor_id
== 0x0106b &&
728 (device_id
== 0x0017 || device_id
== 0x0022)) {
730 pci_set_io_region_addr(d
, 0, 0x80800000);
735 /* default memory mappings */
736 for(i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
740 if (i
== PCI_ROM_SLOT
)
744 pci_config_writel(d
, ofs
, 0xffffffff);
745 val
= pci_config_readl(d
, ofs
);
747 size
= (~(val
& ~0xf)) + 1;
748 if (val
& PCI_ADDRESS_SPACE_IO
)
749 paddr
= &pci_bios_io_addr
;
750 else if (size
>= 0x04000000)
751 paddr
= &pci_bios_bigmem_addr
;
753 paddr
= &pci_bios_mem_addr
;
754 *paddr
= (*paddr
+ size
- 1) & ~(size
- 1);
755 pci_set_io_region_addr(d
, i
, *paddr
);
762 /* map the interrupt */
763 pin
= pci_config_readb(d
, PCI_INTERRUPT_PIN
);
765 pin
= pci_slot_get_pirq(d
, pin
- 1);
766 pic_irq
= pci_irqs
[pin
];
767 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, pic_irq
);
770 if (vendor_id
== 0x8086 && device_id
== 0x7113) {
771 /* PIIX4 Power Management device (for ACPI) */
772 pm_io_base
= PM_IO_BASE
;
773 pci_config_writel(d
, 0x40, pm_io_base
| 1);
774 pci_config_writeb(d
, 0x80, 0x01); /* enable PM io space */
775 smb_io_base
= SMB_IO_BASE
;
776 pci_config_writel(d
, 0x90, smb_io_base
| 1);
777 pci_config_writeb(d
, 0xd2, 0x09); /* enable SMBus io space */
778 pm_sci_int
= pci_config_readb(d
, PCI_INTERRUPT_LINE
);
786 void pci_for_each_device(void (*init_func
)(PCIDevice
*d
))
788 PCIDevice d1
, *d
= &d1
;
790 uint16_t vendor_id
, device_id
;
792 for(bus
= 0; bus
< 1; bus
++) {
793 for(devfn
= 0; devfn
< 256; devfn
++) {
796 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
797 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
798 if (vendor_id
!= 0xffff || device_id
!= 0xffff) {
805 void pci_bios_init(void)
807 pci_bios_io_addr
= 0xc000;
808 pci_bios_mem_addr
= 0xf0000000;
809 pci_bios_bigmem_addr
= ram_size
;
810 if (pci_bios_bigmem_addr
< 0x90000000)
811 pci_bios_bigmem_addr
= 0x90000000;
813 pci_for_each_device(pci_bios_init_bridges
);
815 pci_for_each_device(pci_bios_init_device
);
818 /****************************************************/
819 /* Multi Processor table init */
821 static void putb(uint8_t **pp
, int val
)
829 static void putstr(uint8_t **pp
, const char *str
)
838 static void putle16(uint8_t **pp
, int val
)
847 static void putle32(uint8_t **pp
, int val
)
858 static int mpf_checksum(const uint8_t *data
, int len
)
862 for(i
= 0; i
< len
; i
++)
867 static unsigned long align(unsigned long addr
, unsigned long v
)
869 return (addr
+ v
- 1) & ~(v
- 1);
872 static void mptable_init(void)
874 uint8_t *mp_config_table
, *q
, *float_pointer_struct
;
875 int ioapic_id
, i
, len
;
876 int mp_config_table_size
;
883 #ifdef BX_USE_EBDA_TABLES
884 mp_config_table
= (uint8_t *)(ram_size
- ACPI_DATA_SIZE
- MPTABLE_MAX_SIZE
);
886 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
887 mp_config_table
= (uint8_t *)bios_table_cur_addr
;
890 putstr(&q
, "PCMP"); /* "PCMP signature */
891 putle16(&q
, 0); /* table length (patched later) */
892 putb(&q
, 4); /* spec rev */
893 putb(&q
, 0); /* checksum (patched later) */
895 putstr(&q
, "QEMUCPU "); /* OEM id */
897 putstr(&q
, "BOCHSCPU");
899 putstr(&q
, "0.1 "); /* vendor id */
900 putle32(&q
, 0); /* OEM table ptr */
901 putle16(&q
, 0); /* OEM table size */
902 putle16(&q
, smp_cpus
+ 18); /* entry count */
903 putle32(&q
, 0xfee00000); /* local APIC addr */
904 putle16(&q
, 0); /* ext table length */
905 putb(&q
, 0); /* ext table checksum */
906 putb(&q
, 0); /* reserved */
908 for(i
= 0; i
< smp_cpus
; i
++) {
909 putb(&q
, 0); /* entry type = processor */
910 putb(&q
, i
); /* APIC id */
911 putb(&q
, 0x11); /* local APIC version number */
913 putb(&q
, 3); /* cpu flags: enabled, bootstrap cpu */
915 putb(&q
, 1); /* cpu flags: enabled */
916 putb(&q
, 0); /* cpu signature */
920 putle16(&q
, 0x201); /* feature flags */
923 putle16(&q
, 0); /* reserved */
930 putb(&q
, 1); /* entry type = bus */
931 putb(&q
, 0); /* bus ID */
935 ioapic_id
= smp_cpus
;
936 putb(&q
, 2); /* entry type = I/O APIC */
937 putb(&q
, ioapic_id
); /* apic ID */
938 putb(&q
, 0x11); /* I/O APIC version number */
939 putb(&q
, 1); /* enable */
940 putle32(&q
, 0xfec00000); /* I/O APIC addr */
943 for(i
= 0; i
< 16; i
++) {
944 putb(&q
, 3); /* entry type = I/O interrupt */
945 putb(&q
, 0); /* interrupt type = vectored interrupt */
946 putb(&q
, 0); /* flags: po=0, el=0 */
948 putb(&q
, 0); /* source bus ID = ISA */
949 putb(&q
, i
); /* source bus IRQ */
950 putb(&q
, ioapic_id
); /* dest I/O APIC ID */
951 putb(&q
, i
); /* dest I/O APIC interrupt in */
954 len
= q
- mp_config_table
;
955 mp_config_table
[4] = len
;
956 mp_config_table
[5] = len
>> 8;
958 mp_config_table
[7] = -mpf_checksum(mp_config_table
, q
- mp_config_table
);
960 mp_config_table_size
= q
- mp_config_table
;
962 #ifndef BX_USE_EBDA_TABLES
963 bios_table_cur_addr
+= mp_config_table_size
;
966 /* floating pointer structure */
967 #ifdef BX_USE_EBDA_TABLES
968 ebda_cur_addr
= align(ebda_cur_addr
, 16);
969 float_pointer_struct
= (uint8_t *)ebda_cur_addr
;
971 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
972 float_pointer_struct
= (uint8_t *)bios_table_cur_addr
;
974 q
= float_pointer_struct
;
976 /* pointer to MP config table */
977 putle32(&q
, (unsigned long)mp_config_table
);
979 putb(&q
, 1); /* length in 16 byte units */
980 putb(&q
, 4); /* MP spec revision */
981 putb(&q
, 0); /* checksum (patched later) */
982 putb(&q
, 0); /* MP feature byte 1 */
988 float_pointer_struct
[10] =
989 -mpf_checksum(float_pointer_struct
, q
- float_pointer_struct
);
990 #ifdef BX_USE_EBDA_TABLES
991 ebda_cur_addr
+= (q
- float_pointer_struct
);
993 bios_table_cur_addr
+= (q
- float_pointer_struct
);
995 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
996 (unsigned long)float_pointer_struct
,
997 (unsigned long)mp_config_table
,
998 mp_config_table_size
);
1001 /****************************************************/
1002 /* ACPI tables init */
1004 /* Table structure from Linux kernel (the ACPI tables are under the
1007 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
1008 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
1009 uint32_t length; /* Length of table, in bytes, including header */\
1010 uint8_t revision; /* ACPI Specification minor version # */\
1011 uint8_t checksum; /* To make sum of entire table == 0 */\
1012 uint8_t oem_id [6]; /* OEM identification */\
1013 uint8_t oem_table_id [8]; /* OEM table identification */\
1014 uint32_t oem_revision; /* OEM revision number */\
1015 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
1016 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1019 struct acpi_table_header
/* ACPI common table header */
1021 ACPI_TABLE_HEADER_DEF
1024 struct rsdp_descriptor
/* Root System Descriptor Pointer */
1026 uint8_t signature
[8]; /* ACPI signature, contains "RSD PTR " */
1027 uint8_t checksum
; /* To make sum of struct == 0 */
1028 uint8_t oem_id
[6]; /* OEM identification */
1029 uint8_t revision
; /* Must be 0 for 1.0, 2 for 2.0 */
1030 uint32_t rsdt_physical_address
; /* 32-bit physical address of RSDT */
1031 uint32_t length
; /* XSDT Length in bytes including hdr */
1032 uint64_t xsdt_physical_address
; /* 64-bit physical address of XSDT */
1033 uint8_t extended_checksum
; /* Checksum of entire table */
1034 uint8_t reserved
[3]; /* Reserved field must be 0 */
1038 * ACPI 1.0 Root System Description Table (RSDT)
1040 struct rsdt_descriptor_rev1
1042 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1043 uint32_t table_offset_entry
[2]; /* Array of pointers to other */
1048 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1050 struct facs_descriptor_rev1
1052 uint8_t signature
[4]; /* ACPI Signature */
1053 uint32_t length
; /* Length of structure, in bytes */
1054 uint32_t hardware_signature
; /* Hardware configuration signature */
1055 uint32_t firmware_waking_vector
; /* ACPI OS waking vector */
1056 uint32_t global_lock
; /* Global Lock */
1057 uint32_t S4bios_f
: 1; /* Indicates if S4BIOS support is present */
1058 uint32_t reserved1
: 31; /* Must be 0 */
1059 uint8_t resverved3
[40]; /* Reserved - must be zero */
1064 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1066 struct fadt_descriptor_rev1
1068 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1069 uint32_t firmware_ctrl
; /* Physical address of FACS */
1070 uint32_t dsdt
; /* Physical address of DSDT */
1071 uint8_t model
; /* System Interrupt Model */
1072 uint8_t reserved1
; /* Reserved */
1073 uint16_t sci_int
; /* System vector of SCI interrupt */
1074 uint32_t smi_cmd
; /* Port address of SMI command port */
1075 uint8_t acpi_enable
; /* Value to write to smi_cmd to enable ACPI */
1076 uint8_t acpi_disable
; /* Value to write to smi_cmd to disable ACPI */
1077 uint8_t S4bios_req
; /* Value to write to SMI CMD to enter S4BIOS state */
1078 uint8_t reserved2
; /* Reserved - must be zero */
1079 uint32_t pm1a_evt_blk
; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1080 uint32_t pm1b_evt_blk
; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1081 uint32_t pm1a_cnt_blk
; /* Port address of Power Mgt 1a Control Reg Blk */
1082 uint32_t pm1b_cnt_blk
; /* Port address of Power Mgt 1b Control Reg Blk */
1083 uint32_t pm2_cnt_blk
; /* Port address of Power Mgt 2 Control Reg Blk */
1084 uint32_t pm_tmr_blk
; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1085 uint32_t gpe0_blk
; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1086 uint32_t gpe1_blk
; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1087 uint8_t pm1_evt_len
; /* Byte length of ports at pm1_x_evt_blk */
1088 uint8_t pm1_cnt_len
; /* Byte length of ports at pm1_x_cnt_blk */
1089 uint8_t pm2_cnt_len
; /* Byte Length of ports at pm2_cnt_blk */
1090 uint8_t pm_tmr_len
; /* Byte Length of ports at pm_tm_blk */
1091 uint8_t gpe0_blk_len
; /* Byte Length of ports at gpe0_blk */
1092 uint8_t gpe1_blk_len
; /* Byte Length of ports at gpe1_blk */
1093 uint8_t gpe1_base
; /* Offset in gpe model where gpe1 events start */
1094 uint8_t reserved3
; /* Reserved */
1095 uint16_t plvl2_lat
; /* Worst case HW latency to enter/exit C2 state */
1096 uint16_t plvl3_lat
; /* Worst case HW latency to enter/exit C3 state */
1097 uint16_t flush_size
; /* Size of area read to flush caches */
1098 uint16_t flush_stride
; /* Stride used in flushing caches */
1099 uint8_t duty_offset
; /* Bit location of duty cycle field in p_cnt reg */
1100 uint8_t duty_width
; /* Bit width of duty cycle field in p_cnt reg */
1101 uint8_t day_alrm
; /* Index to day-of-month alarm in RTC CMOS RAM */
1102 uint8_t mon_alrm
; /* Index to month-of-year alarm in RTC CMOS RAM */
1103 uint8_t century
; /* Index to century in RTC CMOS RAM */
1104 uint8_t reserved4
; /* Reserved */
1105 uint8_t reserved4a
; /* Reserved */
1106 uint8_t reserved4b
; /* Reserved */
1108 uint32_t wb_invd
: 1; /* The wbinvd instruction works properly */
1109 uint32_t wb_invd_flush
: 1; /* The wbinvd flushes but does not invalidate */
1110 uint32_t proc_c1
: 1; /* All processors support C1 state */
1111 uint32_t plvl2_up
: 1; /* C2 state works on MP system */
1112 uint32_t pwr_button
: 1; /* Power button is handled as a generic feature */
1113 uint32_t sleep_button
: 1; /* Sleep button is handled as a generic feature, or not present */
1114 uint32_t fixed_rTC
: 1; /* RTC wakeup stat not in fixed register space */
1115 uint32_t rtcs4
: 1; /* RTC wakeup stat not possible from S4 */
1116 uint32_t tmr_val_ext
: 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1117 uint32_t reserved5
: 23; /* Reserved - must be zero */
1124 * MADT values and structures
1127 /* Values for MADT PCATCompat */
1130 #define MULTIPLE_APIC 1
1135 struct multiple_apic_table
1137 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1138 uint32_t local_apic_address
; /* Physical address of local APIC */
1140 uint32_t PCATcompat
: 1; /* A one indicates system also has dual 8259s */
1141 uint32_t reserved1
: 31;
1148 /* Values for Type in APIC_HEADER_DEF */
1150 #define APIC_PROCESSOR 0
1152 #define APIC_XRUPT_OVERRIDE 2
1154 #define APIC_LOCAL_NMI 4
1155 #define APIC_ADDRESS_OVERRIDE 5
1156 #define APIC_IO_SAPIC 6
1157 #define APIC_LOCAL_SAPIC 7
1158 #define APIC_XRUPT_SOURCE 8
1159 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1162 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1164 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1168 /* Sub-structures for MADT */
1170 struct madt_processor_apic
1173 uint8_t processor_id
; /* ACPI processor id */
1174 uint8_t local_apic_id
; /* Processor's local APIC id */
1176 uint32_t processor_enabled
: 1; /* Processor is usable if set */
1177 uint32_t reserved2
: 31; /* Reserved, must be zero */
1186 uint8_t io_apic_id
; /* I/O APIC ID */
1187 uint8_t reserved
; /* Reserved - must be zero */
1188 uint32_t address
; /* APIC physical address */
1189 uint32_t interrupt
; /* Global system interrupt where INTI
1193 struct madt_intsrcovr
{
1201 #include "acpi-dsdt.hex"
1203 static inline uint16_t cpu_to_le16(uint16_t x
)
1208 static inline uint32_t cpu_to_le32(uint32_t x
)
1213 static int acpi_checksum(const uint8_t *data
, int len
)
1217 for(i
= 0; i
< len
; i
++)
1219 return (-sum
) & 0xff;
1222 static void acpi_build_table_header(struct acpi_table_header
*h
,
1225 memcpy(h
->signature
, sig
, 4);
1226 h
->length
= cpu_to_le32(len
);
1229 memcpy(h
->oem_id
, "QEMU ", 6);
1230 memcpy(h
->oem_table_id
, "QEMU", 4);
1232 memcpy(h
->oem_id
, "BOCHS ", 6);
1233 memcpy(h
->oem_table_id
, "BXPC", 4);
1235 memcpy(h
->oem_table_id
+ 4, sig
, 4);
1236 h
->oem_revision
= cpu_to_le32(1);
1238 memcpy(h
->asl_compiler_id
, "QEMU", 4);
1240 memcpy(h
->asl_compiler_id
, "BXPC", 4);
1242 h
->asl_compiler_revision
= cpu_to_le32(1);
1243 h
->checksum
= acpi_checksum((void *)h
, len
);
1246 /* base_addr must be a multiple of 4KB */
1247 void acpi_bios_init(void)
1249 struct rsdp_descriptor
*rsdp
;
1250 struct rsdt_descriptor_rev1
*rsdt
;
1251 struct fadt_descriptor_rev1
*fadt
;
1252 struct facs_descriptor_rev1
*facs
;
1253 struct multiple_apic_table
*madt
;
1255 uint32_t base_addr
, rsdt_addr
, fadt_addr
, addr
, facs_addr
, dsdt_addr
;
1256 uint32_t acpi_tables_size
, madt_addr
, madt_size
;
1259 /* reserve memory space for tables */
1260 #ifdef BX_USE_EBDA_TABLES
1261 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1262 rsdp
= (void *)(ebda_cur_addr
);
1263 ebda_cur_addr
+= sizeof(*rsdp
);
1265 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1266 rsdp
= (void *)(bios_table_cur_addr
);
1267 bios_table_cur_addr
+= sizeof(*rsdp
);
1270 addr
= base_addr
= ram_size
- ACPI_DATA_SIZE
;
1272 rsdt
= (void *)(addr
);
1273 addr
+= sizeof(*rsdt
);
1276 fadt
= (void *)(addr
);
1277 addr
+= sizeof(*fadt
);
1279 /* XXX: FACS should be in RAM */
1280 addr
= (addr
+ 63) & ~63; /* 64 byte alignment for FACS */
1282 facs
= (void *)(addr
);
1283 addr
+= sizeof(*facs
);
1286 dsdt
= (void *)(addr
);
1287 addr
+= sizeof(AmlCode
);
1289 addr
= (addr
+ 7) & ~7;
1291 madt_size
= sizeof(*madt
) +
1292 sizeof(struct madt_processor_apic
) * smp_cpus
+
1293 sizeof(struct madt_io_apic
);
1294 madt
= (void *)(addr
);
1297 acpi_tables_size
= addr
- base_addr
;
1299 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1300 (unsigned long)rsdp
,
1301 (unsigned long)rsdt
, acpi_tables_size
);
1304 memset(rsdp
, 0, sizeof(*rsdp
));
1305 memcpy(rsdp
->signature
, "RSD PTR ", 8);
1307 memcpy(rsdp
->oem_id
, "QEMU ", 6);
1309 memcpy(rsdp
->oem_id
, "BOCHS ", 6);
1311 rsdp
->rsdt_physical_address
= cpu_to_le32(rsdt_addr
);
1312 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
1315 rsdt
->table_offset_entry
[0] = cpu_to_le32(fadt_addr
);
1316 rsdt
->table_offset_entry
[1] = cpu_to_le32(madt_addr
);
1317 acpi_build_table_header((struct acpi_table_header
*)rsdt
,
1318 "RSDT", sizeof(*rsdt
));
1321 memset(fadt
, 0, sizeof(*fadt
));
1322 fadt
->firmware_ctrl
= cpu_to_le32(facs_addr
);
1323 fadt
->dsdt
= cpu_to_le32(dsdt_addr
);
1325 fadt
->reserved1
= 0;
1326 fadt
->sci_int
= cpu_to_le16(pm_sci_int
);
1327 fadt
->smi_cmd
= cpu_to_le32(SMI_CMD_IO_ADDR
);
1328 fadt
->acpi_enable
= 0xf1;
1329 fadt
->acpi_disable
= 0xf0;
1330 fadt
->pm1a_evt_blk
= cpu_to_le32(pm_io_base
);
1331 fadt
->pm1a_cnt_blk
= cpu_to_le32(pm_io_base
+ 0x04);
1332 fadt
->pm_tmr_blk
= cpu_to_le32(pm_io_base
+ 0x08);
1333 fadt
->pm1_evt_len
= 4;
1334 fadt
->pm1_cnt_len
= 2;
1335 fadt
->pm_tmr_len
= 4;
1336 fadt
->plvl2_lat
= cpu_to_le16(0x0fff); // C2 state not supported
1337 fadt
->plvl3_lat
= cpu_to_le16(0x0fff); // C3 state not supported
1338 /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
1339 fadt
->flags
= cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
1340 acpi_build_table_header((struct acpi_table_header
*)fadt
, "FACP",
1344 memset(facs
, 0, sizeof(*facs
));
1345 memcpy(facs
->signature
, "FACS", 4);
1346 facs
->length
= cpu_to_le32(sizeof(*facs
));
1349 memcpy(dsdt
, AmlCode
, sizeof(AmlCode
));
1353 struct madt_processor_apic
*apic
;
1354 struct madt_io_apic
*io_apic
;
1355 struct madt_intsrcovr
*intsrcovr
;
1357 memset(madt
, 0, madt_size
);
1358 madt
->local_apic_address
= cpu_to_le32(0xfee00000);
1359 madt
->flags
= cpu_to_le32(1);
1360 apic
= (void *)(madt
+ 1);
1361 for(i
=0;i
<smp_cpus
;i
++) {
1362 apic
->type
= APIC_PROCESSOR
;
1363 apic
->length
= sizeof(*apic
);
1364 apic
->processor_id
= i
;
1365 apic
->local_apic_id
= i
;
1366 apic
->flags
= cpu_to_le32(1);
1369 io_apic
= (void *)apic
;
1370 io_apic
->type
= APIC_IO
;
1371 io_apic
->length
= sizeof(*io_apic
);
1372 io_apic
->io_apic_id
= smp_cpus
;
1373 io_apic
->address
= cpu_to_le32(0xfec00000);
1374 io_apic
->interrupt
= cpu_to_le32(0);
1376 intsrcovr
= (struct madt_intsrcovr
*)(io_apic
+ 1);
1377 for ( i
= 0; i
< 16; i
++ ) {
1378 if ( PCI_ISA_IRQ_MASK
& (1U << i
) ) {
1379 memset(intsrcovr
, 0, sizeof(*intsrcovr
));
1380 intsrcovr
->type
= APIC_XRUPT_OVERRIDE
;
1381 intsrcovr
->length
= sizeof(*intsrcovr
);
1382 intsrcovr
->source
= i
;
1384 intsrcovr
->flags
= 0xd; /* active high, level triggered */
1386 /* No need for a INT source override structure. */
1390 madt_size
+= sizeof(struct madt_intsrcovr
);
1392 acpi_build_table_header((struct acpi_table_header
*)madt
,
1397 void rombios32_init(void)
1399 BX_INFO("Starting rombios32\n");
1409 if (bios_table_cur_addr
!= 0) {
1416 bios_lock_shadow_ram();