1 /////////////////////////////////////////////////////////////////////////
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
58 #define APIC_ENABLED 0x0100
60 #define AP_BOOT_ADDR 0x10000
62 #define MPTABLE_MAX_SIZE 0x00002000
63 #define SMI_CMD_IO_ADDR 0xb2
65 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
67 static inline void outl(int addr
, int val
)
69 asm volatile ("outl %1, %w0" : : "d" (addr
), "a" (val
));
72 static inline void outw(int addr
, int val
)
74 asm volatile ("outw %w1, %w0" : : "d" (addr
), "a" (val
));
77 static inline void outb(int addr
, int val
)
79 asm volatile ("outb %b1, %w0" : : "d" (addr
), "a" (val
));
82 static inline uint32_t inl(int addr
)
85 asm volatile ("inl %w1, %0" : "=a" (val
) : "d" (addr
));
89 static inline uint16_t inw(int addr
)
92 asm volatile ("inw %w1, %w0" : "=a" (val
) : "d" (addr
));
96 static inline uint8_t inb(int addr
)
99 asm volatile ("inb %w1, %b0" : "=a" (val
) : "d" (addr
));
103 static inline void writel(void *addr
, uint32_t val
)
105 *(volatile uint32_t *)addr
= val
;
108 static inline void writew(void *addr
, uint16_t val
)
110 *(volatile uint16_t *)addr
= val
;
113 static inline void writeb(void *addr
, uint8_t val
)
115 *(volatile uint8_t *)addr
= val
;
118 static inline uint32_t readl(const void *addr
)
120 return *(volatile const uint32_t *)addr
;
123 static inline uint16_t readw(const void *addr
)
125 return *(volatile const uint16_t *)addr
;
128 static inline uint8_t readb(const void *addr
)
130 return *(volatile const uint8_t *)addr
;
133 static inline void putc(int c
)
138 static inline int isdigit(int c
)
140 return c
>= '0' && c
<= '9';
143 void *memset(void *d1
, int val
, size_t len
)
153 void *memcpy(void *d1
, const void *s1
, size_t len
)
156 const uint8_t *s
= s1
;
164 void *memmove(void *d1
, const void *s1
, size_t len
)
167 const uint8_t *s
= s1
;
183 size_t strlen(const char *s
)
186 for(s1
= s
; *s1
!= '\0'; s1
++);
190 /* from BSD ppp sources */
191 int vsnprintf(char *buf
, int buflen
, const char *fmt
, va_list args
)
194 int width
, prec
, fillch
;
196 unsigned long val
= 0;
200 static const char hexchars
[] = "0123456789abcdef";
205 for (f
= fmt
; *f
!= '%' && *f
!= 0; ++f
)
211 memcpy(buf
, fmt
, len
);
226 width
= va_arg(args
, int);
230 width
= width
* 10 + c
- '0';
237 prec
= va_arg(args
, int);
241 prec
= prec
* 10 + c
- '0';
260 i
= va_arg(args
, int);
269 val
= va_arg(args
, unsigned int);
274 val
= va_arg(args
, unsigned int);
278 val
= (unsigned long) va_arg(args
, void *);
283 str
= va_arg(args
, char *);
286 num
[0] = va_arg(args
, int);
293 --fmt
; /* so %z outputs %z etc. */
298 str
= num
+ sizeof(num
);
300 while (str
> num
+ neg
) {
301 *--str
= hexchars
[val
% base
];
303 if (--prec
<= 0 && val
== 0)
315 len
= num
+ sizeof(num
) - 1 - str
;
318 if (prec
> 0 && len
> prec
)
324 if ((n
= width
- len
) > 0) {
332 memcpy(buf
, str
, len
);
340 void bios_printf(int flags
, const char *fmt
, ...)
347 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
357 for(i
= 0; i
< n
; i
++) {
359 /* approximative ! */
360 for(j
= 0; j
< 1000000; j
++);
365 r1
= inb(0x61) & 0x10;
367 r2
= inb(0x61) & 0x10;
379 uint32_t cpuid_features
;
380 uint32_t cpuid_ext_features
;
381 unsigned long ram_size
;
382 #ifdef BX_USE_EBDA_TABLES
383 unsigned long ebda_cur_addr
;
386 uint32_t pm_io_base
, smb_io_base
;
388 unsigned long bios_table_cur_addr
;
389 unsigned long bios_table_end_addr
;
393 uint32_t eax
, ebx
, ecx
, edx
;
394 cpuid(1, eax
, ebx
, ecx
, edx
);
395 cpuid_features
= edx
;
396 cpuid_ext_features
= ecx
;
399 static int cmos_readb(int addr
)
407 if (cmos_readb(0x34) | cmos_readb(0x35))
408 ram_size
= (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
411 ram_size
= (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
412 #ifdef BX_USE_EBDA_TABLES
413 ebda_cur_addr
= ((*(uint16_t *)(0x40e)) << 4) + 0x380;
415 BX_INFO("ram_size=0x%08lx\n", ram_size
);
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
);
449 smp_cpus
= readw((void *)CPU_COUNT_ADDR
);
451 BX_INFO("Found %d cpu(s)\n", smp_cpus
);
454 /****************************************************/
457 #define PCI_ADDRESS_SPACE_MEM 0x00
458 #define PCI_ADDRESS_SPACE_IO 0x01
459 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
461 #define PCI_ROM_SLOT 6
462 #define PCI_NUM_REGIONS 7
464 #define PCI_DEVICES_MAX 64
466 #define PCI_VENDOR_ID 0x00 /* 16 bits */
467 #define PCI_DEVICE_ID 0x02 /* 16 bits */
468 #define PCI_COMMAND 0x04 /* 16 bits */
469 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
470 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
471 #define PCI_CLASS_DEVICE 0x0a /* Device class */
472 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
473 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
474 #define PCI_MIN_GNT 0x3e /* 8 bits */
475 #define PCI_MAX_LAT 0x3f /* 8 bits */
477 typedef struct PCIDevice
{
482 static uint32_t pci_bios_io_addr
;
483 static uint32_t pci_bios_mem_addr
;
484 static uint32_t pci_bios_bigmem_addr
;
485 /* host irqs corresponding to PCI irqs A-D */
486 static uint8_t pci_irqs
[4] = { 11, 9, 11, 9 };
487 static PCIDevice i440_pcidev
;
489 static void pci_config_writel(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
491 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
495 static void pci_config_writew(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
497 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
498 outw(0xcfc + (addr
& 2), val
);
501 static void pci_config_writeb(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
503 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
504 outb(0xcfc + (addr
& 3), val
);
507 static uint32_t pci_config_readl(PCIDevice
*d
, uint32_t addr
)
509 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
513 static uint32_t pci_config_readw(PCIDevice
*d
, uint32_t addr
)
515 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
516 return inw(0xcfc + (addr
& 2));
519 static uint32_t pci_config_readb(PCIDevice
*d
, uint32_t addr
)
521 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
522 return inb(0xcfc + (addr
& 3));
525 static void pci_set_io_region_addr(PCIDevice
*d
, int region_num
, uint32_t addr
)
528 uint32_t ofs
, old_addr
;
530 if ( region_num
== PCI_ROM_SLOT
) {
533 ofs
= 0x10 + region_num
* 4;
536 old_addr
= pci_config_readl(d
, ofs
);
538 pci_config_writel(d
, ofs
, addr
);
539 BX_INFO("region %d: 0x%08x\n", region_num
, addr
);
541 /* enable memory mappings */
542 cmd
= pci_config_readw(d
, PCI_COMMAND
);
543 if ( region_num
== PCI_ROM_SLOT
)
545 else if (old_addr
& PCI_ADDRESS_SPACE_IO
)
549 pci_config_writew(d
, PCI_COMMAND
, cmd
);
552 /* return the global irq number corresponding to a given device irq
553 pin. We could also use the bus number to have a more precise
555 static int pci_slot_get_pirq(PCIDevice
*pci_dev
, int irq_num
)
558 slot_addend
= (pci_dev
->devfn
>> 3) - 1;
559 return (irq_num
+ slot_addend
) & 3;
562 static int find_bios_table_area(void)
565 for(addr
= 0xf0000; addr
< 0x100000; addr
+= 16) {
566 if (*(uint32_t *)addr
== 0xaafb4442) {
567 bios_table_cur_addr
= addr
+ 8;
568 bios_table_end_addr
= bios_table_cur_addr
+ *(uint32_t *)(addr
+ 4);
569 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
570 bios_table_cur_addr
, bios_table_end_addr
);
577 static void bios_shadow_init(PCIDevice
*d
)
581 if (find_bios_table_area() < 0)
584 /* remap the BIOS to shadow RAM an keep it read/write while we
585 are writing tables */
586 v
= pci_config_readb(d
, 0x59);
588 pci_config_writeb(d
, 0x59, v
);
589 memcpy((void *)BIOS_TMP_STORAGE
, (void *)0x000f0000, 0x10000);
591 pci_config_writeb(d
, 0x59, v
);
592 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE
, 0x10000);
597 static void bios_lock_shadow_ram(void)
599 PCIDevice
*d
= &i440_pcidev
;
603 v
= pci_config_readb(d
, 0x59);
604 v
= (v
& 0x0f) | (0x10);
605 pci_config_writeb(d
, 0x59, v
);
608 static void pci_bios_init_bridges(PCIDevice
*d
)
610 uint16_t vendor_id
, device_id
;
612 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
613 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
615 if (vendor_id
== 0x8086 && device_id
== 0x7000) {
623 for(i
= 0; i
< 4; i
++) {
625 /* set to trigger level */
626 elcr
[irq
>> 3] |= (1 << (irq
& 7));
627 /* activate irq remapping in PIIX */
628 pci_config_writeb(d
, 0x60 + i
, irq
);
630 outb(0x4d0, elcr
[0]);
631 outb(0x4d1, elcr
[1]);
632 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
634 } else if (vendor_id
== 0x8086 && device_id
== 0x1237) {
635 /* i440 PCI bridge */
640 extern uint8_t smm_relocation_start
, smm_relocation_end
;
641 extern uint8_t smm_code_start
, smm_code_end
;
644 static void smm_init(PCIDevice
*d
)
646 /* copy the SMM relocation code */
647 memcpy((void *)0x38000, &smm_relocation_start
,
648 &smm_relocation_end
- &smm_relocation_start
);
650 /* enable SMI generation when writing to the APMC register */
651 pci_config_writel(d
, 0x58, pci_config_readl(d
, 0x58) | (1 << 25));
653 /* init APM status port */
656 /* raise an SMI interrupt */
659 /* wait until SMM code executed */
660 while (inb(0xb3) != 0x00);
662 /* enable the SMM memory window */
663 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x48);
665 /* copy the SMM code */
666 memcpy((void *)0xa8000, &smm_code_start
,
667 &smm_code_end
- &smm_code_start
);
670 /* close the SMM memory window and enable normal SMM */
671 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x08);
675 static void pci_bios_init_device(PCIDevice
*d
)
679 int i
, pin
, pic_irq
, vendor_id
, device_id
;
681 class = pci_config_readw(d
, PCI_CLASS_DEVICE
);
682 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
683 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
684 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
685 d
->bus
, d
->devfn
, vendor_id
, device_id
);
688 if (vendor_id
== 0x8086 && device_id
== 0x7010) {
690 pci_config_writew(d
, 0x40, 0x8000); // enable IDE0
691 pci_config_writew(d
, 0x42, 0x8000); // enable IDE1
694 /* IDE: we map it as in ISA mode */
695 pci_set_io_region_addr(d
, 0, 0x1f0);
696 pci_set_io_region_addr(d
, 1, 0x3f4);
697 pci_set_io_region_addr(d
, 2, 0x170);
698 pci_set_io_region_addr(d
, 3, 0x374);
702 if (vendor_id
!= 0x1234)
704 /* VGA: map frame buffer to default Bochs VBE address */
705 pci_set_io_region_addr(d
, 0, 0xE0000000);
709 if (vendor_id
== 0x1014) {
711 if (device_id
== 0x0046 || device_id
== 0xFFFF) {
713 pci_set_io_region_addr(d
, 0, 0x80800000 + 0x00040000);
718 if (vendor_id
== 0x0106b &&
719 (device_id
== 0x0017 || device_id
== 0x0022)) {
721 pci_set_io_region_addr(d
, 0, 0x80800000);
726 /* default memory mappings */
727 for(i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
731 if (i
== PCI_ROM_SLOT
)
735 pci_config_writel(d
, ofs
, 0xffffffff);
736 val
= pci_config_readl(d
, ofs
);
738 size
= (~(val
& ~0xf)) + 1;
739 if (val
& PCI_ADDRESS_SPACE_IO
)
740 paddr
= &pci_bios_io_addr
;
741 else if (size
>= 0x04000000)
742 paddr
= &pci_bios_bigmem_addr
;
744 paddr
= &pci_bios_mem_addr
;
745 *paddr
= (*paddr
+ size
- 1) & ~(size
- 1);
746 pci_set_io_region_addr(d
, i
, *paddr
);
753 /* map the interrupt */
754 pin
= pci_config_readb(d
, PCI_INTERRUPT_PIN
);
756 pin
= pci_slot_get_pirq(d
, pin
- 1);
757 pic_irq
= pci_irqs
[pin
];
758 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, pic_irq
);
761 if (vendor_id
== 0x8086 && device_id
== 0x7113) {
762 /* PIIX4 Power Management device (for ACPI) */
763 pm_io_base
= PM_IO_BASE
;
764 pci_config_writel(d
, 0x40, pm_io_base
| 1);
765 pci_config_writeb(d
, 0x80, 0x01); /* enable PM io space */
766 smb_io_base
= SMB_IO_BASE
;
767 pci_config_writel(d
, 0x90, smb_io_base
| 1);
768 pci_config_writeb(d
, 0xd2, 0x09); /* enable SMBus io space */
769 pm_sci_int
= pci_config_readb(d
, PCI_INTERRUPT_LINE
);
777 void pci_for_each_device(void (*init_func
)(PCIDevice
*d
))
779 PCIDevice d1
, *d
= &d1
;
781 uint16_t vendor_id
, device_id
;
783 for(bus
= 0; bus
< 1; bus
++) {
784 for(devfn
= 0; devfn
< 256; devfn
++) {
787 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
788 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
789 if (vendor_id
!= 0xffff || device_id
!= 0xffff) {
796 void pci_bios_init(void)
798 pci_bios_io_addr
= 0xc000;
799 pci_bios_mem_addr
= 0xf0000000;
800 pci_bios_bigmem_addr
= ram_size
;
801 if (pci_bios_bigmem_addr
< 0x90000000)
802 pci_bios_bigmem_addr
= 0x90000000;
804 pci_for_each_device(pci_bios_init_bridges
);
806 pci_for_each_device(pci_bios_init_device
);
809 /****************************************************/
810 /* Multi Processor table init */
812 static void putb(uint8_t **pp
, int val
)
820 static void putstr(uint8_t **pp
, const char *str
)
829 static void putle16(uint8_t **pp
, int val
)
838 static void putle32(uint8_t **pp
, int val
)
849 static int mpf_checksum(const uint8_t *data
, int len
)
853 for(i
= 0; i
< len
; i
++)
858 static unsigned long align(unsigned long addr
, unsigned long v
)
860 return (addr
+ v
- 1) & ~(v
- 1);
863 static void mptable_init(void)
865 uint8_t *mp_config_table
, *q
, *float_pointer_struct
;
866 int ioapic_id
, i
, len
;
867 int mp_config_table_size
;
869 #ifdef BX_USE_EBDA_TABLES
870 mp_config_table
= (uint8_t *)(ram_size
- ACPI_DATA_SIZE
- MPTABLE_MAX_SIZE
);
872 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
873 mp_config_table
= (uint8_t *)bios_table_cur_addr
;
876 putstr(&q
, "PCMP"); /* "PCMP signature */
877 putle16(&q
, 0); /* table length (patched later) */
878 putb(&q
, 4); /* spec rev */
879 putb(&q
, 0); /* checksum (patched later) */
881 putstr(&q
, "QEMUCPU "); /* OEM id */
883 putstr(&q
, "BOCHSCPU");
885 putstr(&q
, "0.1 "); /* vendor id */
886 putle32(&q
, 0); /* OEM table ptr */
887 putle16(&q
, 0); /* OEM table size */
888 putle16(&q
, smp_cpus
+ 18); /* entry count */
889 putle32(&q
, 0xfee00000); /* local APIC addr */
890 putle16(&q
, 0); /* ext table length */
891 putb(&q
, 0); /* ext table checksum */
892 putb(&q
, 0); /* reserved */
894 for(i
= 0; i
< smp_cpus
; i
++) {
895 putb(&q
, 0); /* entry type = processor */
896 putb(&q
, i
); /* APIC id */
897 putb(&q
, 0x11); /* local APIC version number */
899 putb(&q
, 3); /* cpu flags: enabled, bootstrap cpu */
901 putb(&q
, 1); /* cpu flags: enabled */
902 putb(&q
, 0); /* cpu signature */
906 putle16(&q
, 0x201); /* feature flags */
909 putle16(&q
, 0); /* reserved */
916 putb(&q
, 1); /* entry type = bus */
917 putb(&q
, 0); /* bus ID */
921 ioapic_id
= smp_cpus
;
922 putb(&q
, 2); /* entry type = I/O APIC */
923 putb(&q
, ioapic_id
); /* apic ID */
924 putb(&q
, 0x11); /* I/O APIC version number */
925 putb(&q
, 1); /* enable */
926 putle32(&q
, 0xfec00000); /* I/O APIC addr */
929 for(i
= 0; i
< 16; i
++) {
930 putb(&q
, 3); /* entry type = I/O interrupt */
931 putb(&q
, 0); /* interrupt type = vectored interrupt */
932 putb(&q
, 0); /* flags: po=0, el=0 */
934 putb(&q
, 0); /* source bus ID = ISA */
935 putb(&q
, i
); /* source bus IRQ */
936 putb(&q
, ioapic_id
); /* dest I/O APIC ID */
937 putb(&q
, i
); /* dest I/O APIC interrupt in */
940 len
= q
- mp_config_table
;
941 mp_config_table
[4] = len
;
942 mp_config_table
[5] = len
>> 8;
944 mp_config_table
[7] = -mpf_checksum(mp_config_table
, q
- mp_config_table
);
946 mp_config_table_size
= q
- mp_config_table
;
948 #ifndef BX_USE_EBDA_TABLES
949 bios_table_cur_addr
+= mp_config_table_size
;
952 /* floating pointer structure */
953 #ifdef BX_USE_EBDA_TABLES
954 ebda_cur_addr
= align(ebda_cur_addr
, 16);
955 float_pointer_struct
= (uint8_t *)ebda_cur_addr
;
957 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
958 float_pointer_struct
= (uint8_t *)bios_table_cur_addr
;
960 q
= float_pointer_struct
;
962 /* pointer to MP config table */
963 putle32(&q
, (unsigned long)mp_config_table
);
965 putb(&q
, 1); /* length in 16 byte units */
966 putb(&q
, 4); /* MP spec revision */
967 putb(&q
, 0); /* checksum (patched later) */
968 putb(&q
, 0); /* MP feature byte 1 */
974 float_pointer_struct
[10] =
975 -mpf_checksum(float_pointer_struct
, q
- float_pointer_struct
);
976 #ifdef BX_USE_EBDA_TABLES
977 ebda_cur_addr
+= (q
- float_pointer_struct
);
979 bios_table_cur_addr
+= (q
- float_pointer_struct
);
981 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
982 (unsigned long)float_pointer_struct
,
983 (unsigned long)mp_config_table
,
984 mp_config_table_size
);
987 /****************************************************/
988 /* ACPI tables init */
990 /* Table structure from Linux kernel (the ACPI tables are under the
993 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
994 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
995 uint32_t length; /* Length of table, in bytes, including header */\
996 uint8_t revision; /* ACPI Specification minor version # */\
997 uint8_t checksum; /* To make sum of entire table == 0 */\
998 uint8_t oem_id [6]; /* OEM identification */\
999 uint8_t oem_table_id [8]; /* OEM table identification */\
1000 uint32_t oem_revision; /* OEM revision number */\
1001 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
1002 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1005 struct acpi_table_header
/* ACPI common table header */
1007 ACPI_TABLE_HEADER_DEF
1010 struct rsdp_descriptor
/* Root System Descriptor Pointer */
1012 uint8_t signature
[8]; /* ACPI signature, contains "RSD PTR " */
1013 uint8_t checksum
; /* To make sum of struct == 0 */
1014 uint8_t oem_id
[6]; /* OEM identification */
1015 uint8_t revision
; /* Must be 0 for 1.0, 2 for 2.0 */
1016 uint32_t rsdt_physical_address
; /* 32-bit physical address of RSDT */
1017 uint32_t length
; /* XSDT Length in bytes including hdr */
1018 uint64_t xsdt_physical_address
; /* 64-bit physical address of XSDT */
1019 uint8_t extended_checksum
; /* Checksum of entire table */
1020 uint8_t reserved
[3]; /* Reserved field must be 0 */
1024 * ACPI 1.0 Root System Description Table (RSDT)
1026 struct rsdt_descriptor_rev1
1028 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1029 uint32_t table_offset_entry
[2]; /* Array of pointers to other */
1034 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1036 struct facs_descriptor_rev1
1038 uint8_t signature
[4]; /* ACPI Signature */
1039 uint32_t length
; /* Length of structure, in bytes */
1040 uint32_t hardware_signature
; /* Hardware configuration signature */
1041 uint32_t firmware_waking_vector
; /* ACPI OS waking vector */
1042 uint32_t global_lock
; /* Global Lock */
1043 uint32_t S4bios_f
: 1; /* Indicates if S4BIOS support is present */
1044 uint32_t reserved1
: 31; /* Must be 0 */
1045 uint8_t resverved3
[40]; /* Reserved - must be zero */
1050 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1052 struct fadt_descriptor_rev1
1054 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1055 uint32_t firmware_ctrl
; /* Physical address of FACS */
1056 uint32_t dsdt
; /* Physical address of DSDT */
1057 uint8_t model
; /* System Interrupt Model */
1058 uint8_t reserved1
; /* Reserved */
1059 uint16_t sci_int
; /* System vector of SCI interrupt */
1060 uint32_t smi_cmd
; /* Port address of SMI command port */
1061 uint8_t acpi_enable
; /* Value to write to smi_cmd to enable ACPI */
1062 uint8_t acpi_disable
; /* Value to write to smi_cmd to disable ACPI */
1063 uint8_t S4bios_req
; /* Value to write to SMI CMD to enter S4BIOS state */
1064 uint8_t reserved2
; /* Reserved - must be zero */
1065 uint32_t pm1a_evt_blk
; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1066 uint32_t pm1b_evt_blk
; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1067 uint32_t pm1a_cnt_blk
; /* Port address of Power Mgt 1a Control Reg Blk */
1068 uint32_t pm1b_cnt_blk
; /* Port address of Power Mgt 1b Control Reg Blk */
1069 uint32_t pm2_cnt_blk
; /* Port address of Power Mgt 2 Control Reg Blk */
1070 uint32_t pm_tmr_blk
; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1071 uint32_t gpe0_blk
; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1072 uint32_t gpe1_blk
; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1073 uint8_t pm1_evt_len
; /* Byte length of ports at pm1_x_evt_blk */
1074 uint8_t pm1_cnt_len
; /* Byte length of ports at pm1_x_cnt_blk */
1075 uint8_t pm2_cnt_len
; /* Byte Length of ports at pm2_cnt_blk */
1076 uint8_t pm_tmr_len
; /* Byte Length of ports at pm_tm_blk */
1077 uint8_t gpe0_blk_len
; /* Byte Length of ports at gpe0_blk */
1078 uint8_t gpe1_blk_len
; /* Byte Length of ports at gpe1_blk */
1079 uint8_t gpe1_base
; /* Offset in gpe model where gpe1 events start */
1080 uint8_t reserved3
; /* Reserved */
1081 uint16_t plvl2_lat
; /* Worst case HW latency to enter/exit C2 state */
1082 uint16_t plvl3_lat
; /* Worst case HW latency to enter/exit C3 state */
1083 uint16_t flush_size
; /* Size of area read to flush caches */
1084 uint16_t flush_stride
; /* Stride used in flushing caches */
1085 uint8_t duty_offset
; /* Bit location of duty cycle field in p_cnt reg */
1086 uint8_t duty_width
; /* Bit width of duty cycle field in p_cnt reg */
1087 uint8_t day_alrm
; /* Index to day-of-month alarm in RTC CMOS RAM */
1088 uint8_t mon_alrm
; /* Index to month-of-year alarm in RTC CMOS RAM */
1089 uint8_t century
; /* Index to century in RTC CMOS RAM */
1090 uint8_t reserved4
; /* Reserved */
1091 uint8_t reserved4a
; /* Reserved */
1092 uint8_t reserved4b
; /* Reserved */
1094 uint32_t wb_invd
: 1; /* The wbinvd instruction works properly */
1095 uint32_t wb_invd_flush
: 1; /* The wbinvd flushes but does not invalidate */
1096 uint32_t proc_c1
: 1; /* All processors support C1 state */
1097 uint32_t plvl2_up
: 1; /* C2 state works on MP system */
1098 uint32_t pwr_button
: 1; /* Power button is handled as a generic feature */
1099 uint32_t sleep_button
: 1; /* Sleep button is handled as a generic feature, or not present */
1100 uint32_t fixed_rTC
: 1; /* RTC wakeup stat not in fixed register space */
1101 uint32_t rtcs4
: 1; /* RTC wakeup stat not possible from S4 */
1102 uint32_t tmr_val_ext
: 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1103 uint32_t reserved5
: 23; /* Reserved - must be zero */
1110 * MADT values and structures
1113 /* Values for MADT PCATCompat */
1116 #define MULTIPLE_APIC 1
1121 struct multiple_apic_table
1123 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1124 uint32_t local_apic_address
; /* Physical address of local APIC */
1126 uint32_t PCATcompat
: 1; /* A one indicates system also has dual 8259s */
1127 uint32_t reserved1
: 31;
1134 /* Values for Type in APIC_HEADER_DEF */
1136 #define APIC_PROCESSOR 0
1138 #define APIC_XRUPT_OVERRIDE 2
1140 #define APIC_LOCAL_NMI 4
1141 #define APIC_ADDRESS_OVERRIDE 5
1142 #define APIC_IO_SAPIC 6
1143 #define APIC_LOCAL_SAPIC 7
1144 #define APIC_XRUPT_SOURCE 8
1145 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1148 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1150 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1154 /* Sub-structures for MADT */
1156 struct madt_processor_apic
1159 uint8_t processor_id
; /* ACPI processor id */
1160 uint8_t local_apic_id
; /* Processor's local APIC id */
1162 uint32_t processor_enabled
: 1; /* Processor is usable if set */
1163 uint32_t reserved2
: 31; /* Reserved, must be zero */
1172 uint8_t io_apic_id
; /* I/O APIC ID */
1173 uint8_t reserved
; /* Reserved - must be zero */
1174 uint32_t address
; /* APIC physical address */
1175 uint32_t interrupt
; /* Global system interrupt where INTI
1179 #include "acpi-dsdt.hex"
1181 static inline uint16_t cpu_to_le16(uint16_t x
)
1186 static inline uint32_t cpu_to_le32(uint32_t x
)
1191 static int acpi_checksum(const uint8_t *data
, int len
)
1195 for(i
= 0; i
< len
; i
++)
1197 return (-sum
) & 0xff;
1200 static void acpi_build_table_header(struct acpi_table_header
*h
,
1201 char *sig
, int len
, uint8_t rev
)
1203 memcpy(h
->signature
, sig
, 4);
1204 h
->length
= cpu_to_le32(len
);
1207 memcpy(h
->oem_id
, "QEMU ", 6);
1208 memcpy(h
->oem_table_id
, "QEMU", 4);
1210 memcpy(h
->oem_id
, "BOCHS ", 6);
1211 memcpy(h
->oem_table_id
, "BXPC", 4);
1213 memcpy(h
->oem_table_id
+ 4, sig
, 4);
1214 h
->oem_revision
= cpu_to_le32(1);
1216 memcpy(h
->asl_compiler_id
, "QEMU", 4);
1218 memcpy(h
->asl_compiler_id
, "BXPC", 4);
1220 h
->asl_compiler_revision
= cpu_to_le32(1);
1221 h
->checksum
= acpi_checksum((void *)h
, len
);
1224 /* base_addr must be a multiple of 4KB */
1225 void acpi_bios_init(void)
1227 struct rsdp_descriptor
*rsdp
;
1228 struct rsdt_descriptor_rev1
*rsdt
;
1229 struct fadt_descriptor_rev1
*fadt
;
1230 struct facs_descriptor_rev1
*facs
;
1231 struct multiple_apic_table
*madt
;
1233 uint32_t base_addr
, rsdt_addr
, fadt_addr
, addr
, facs_addr
, dsdt_addr
;
1234 uint32_t acpi_tables_size
, madt_addr
, madt_size
;
1237 /* reserve memory space for tables */
1238 #ifdef BX_USE_EBDA_TABLES
1239 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1240 rsdp
= (void *)(ebda_cur_addr
);
1241 ebda_cur_addr
+= sizeof(*rsdp
);
1243 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1244 rsdp
= (void *)(bios_table_cur_addr
);
1245 bios_table_cur_addr
+= sizeof(*rsdp
);
1248 addr
= base_addr
= ram_size
- ACPI_DATA_SIZE
;
1250 rsdt
= (void *)(addr
);
1251 addr
+= sizeof(*rsdt
);
1254 fadt
= (void *)(addr
);
1255 addr
+= sizeof(*fadt
);
1257 /* XXX: FACS should be in RAM */
1258 addr
= (addr
+ 63) & ~63; /* 64 byte alignment for FACS */
1260 facs
= (void *)(addr
);
1261 addr
+= sizeof(*facs
);
1264 dsdt
= (void *)(addr
);
1265 addr
+= sizeof(AmlCode
);
1267 addr
= (addr
+ 7) & ~7;
1269 madt_size
= sizeof(*madt
) +
1270 sizeof(struct madt_processor_apic
) * smp_cpus
+
1271 sizeof(struct madt_io_apic
);
1272 madt
= (void *)(addr
);
1275 acpi_tables_size
= addr
- base_addr
;
1277 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1278 (unsigned long)rsdp
,
1279 (unsigned long)rsdt
, acpi_tables_size
);
1282 memset(rsdp
, 0, sizeof(*rsdp
));
1283 memcpy(rsdp
->signature
, "RSD PTR ", 8);
1285 memcpy(rsdp
->oem_id
, "QEMU ", 6);
1287 memcpy(rsdp
->oem_id
, "BOCHS ", 6);
1289 rsdp
->rsdt_physical_address
= cpu_to_le32(rsdt_addr
);
1290 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
1293 memset(rsdt
, 0, sizeof(*rsdt
));
1294 rsdt
->table_offset_entry
[0] = cpu_to_le32(fadt_addr
);
1295 rsdt
->table_offset_entry
[1] = cpu_to_le32(madt_addr
);
1296 acpi_build_table_header((struct acpi_table_header
*)rsdt
,
1297 "RSDT", sizeof(*rsdt
), 1);
1300 memset(fadt
, 0, sizeof(*fadt
));
1301 fadt
->firmware_ctrl
= cpu_to_le32(facs_addr
);
1302 fadt
->dsdt
= cpu_to_le32(dsdt_addr
);
1304 fadt
->reserved1
= 0;
1305 fadt
->sci_int
= cpu_to_le16(pm_sci_int
);
1306 fadt
->smi_cmd
= cpu_to_le32(SMI_CMD_IO_ADDR
);
1307 fadt
->acpi_enable
= 0xf1;
1308 fadt
->acpi_disable
= 0xf0;
1309 fadt
->pm1a_evt_blk
= cpu_to_le32(pm_io_base
);
1310 fadt
->pm1a_cnt_blk
= cpu_to_le32(pm_io_base
+ 0x04);
1311 fadt
->pm_tmr_blk
= cpu_to_le32(pm_io_base
+ 0x08);
1312 fadt
->pm1_evt_len
= 4;
1313 fadt
->pm1_cnt_len
= 2;
1314 fadt
->pm_tmr_len
= 4;
1315 fadt
->plvl2_lat
= cpu_to_le16(50);
1316 fadt
->plvl3_lat
= cpu_to_le16(50);
1317 fadt
->plvl3_lat
= cpu_to_le16(50);
1318 /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
1319 fadt
->flags
= cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
1320 acpi_build_table_header((struct acpi_table_header
*)fadt
, "FACP",
1324 memset(facs
, 0, sizeof(*facs
));
1325 memcpy(facs
->signature
, "FACS", 4);
1326 facs
->length
= cpu_to_le32(sizeof(*facs
));
1329 memcpy(dsdt
, AmlCode
, sizeof(AmlCode
));
1333 struct madt_processor_apic
*apic
;
1334 struct madt_io_apic
*io_apic
;
1336 memset(madt
, 0, madt_size
);
1337 madt
->local_apic_address
= cpu_to_le32(0xfee00000);
1338 madt
->flags
= cpu_to_le32(1);
1339 apic
= (void *)(madt
+ 1);
1340 for(i
=0;i
<smp_cpus
;i
++) {
1341 apic
->type
= APIC_PROCESSOR
;
1342 apic
->length
= sizeof(*apic
);
1343 apic
->processor_id
= i
;
1344 apic
->local_apic_id
= i
;
1345 apic
->flags
= cpu_to_le32(1);
1348 io_apic
= (void *)apic
;
1349 io_apic
->type
= APIC_IO
;
1350 io_apic
->length
= sizeof(*io_apic
);
1351 io_apic
->io_apic_id
= smp_cpus
;
1352 io_apic
->address
= cpu_to_le32(0xfec00000);
1353 io_apic
->interrupt
= cpu_to_le32(0);
1355 acpi_build_table_header((struct acpi_table_header
*)madt
,
1356 "APIC", madt_size
, 1);
1360 void rombios32_init(void)
1362 BX_INFO("Starting rombios32\n");
1372 if (bios_table_cur_addr
!= 0) {
1379 bios_lock_shadow_ram();