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 #define MSR_MTRRcap 0x000000fe
71 #define MSR_MTRRfix64K_00000 0x00000250
72 #define MSR_MTRRfix16K_80000 0x00000258
73 #define MSR_MTRRfix16K_A0000 0x00000259
74 #define MSR_MTRRfix4K_C0000 0x00000268
75 #define MSR_MTRRfix4K_C8000 0x00000269
76 #define MSR_MTRRfix4K_D0000 0x0000026a
77 #define MSR_MTRRfix4K_D8000 0x0000026b
78 #define MSR_MTRRfix4K_E0000 0x0000026c
79 #define MSR_MTRRfix4K_E8000 0x0000026d
80 #define MSR_MTRRfix4K_F0000 0x0000026e
81 #define MSR_MTRRfix4K_F8000 0x0000026f
82 #define MSR_MTRRdefType 0x000002ff
84 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
85 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
87 static inline void outl(int addr
, int val
)
89 asm volatile ("outl %1, %w0" : : "d" (addr
), "a" (val
));
92 static inline void outw(int addr
, int val
)
94 asm volatile ("outw %w1, %w0" : : "d" (addr
), "a" (val
));
97 static inline void outb(int addr
, int val
)
99 asm volatile ("outb %b1, %w0" : : "d" (addr
), "a" (val
));
102 static inline uint32_t inl(int addr
)
105 asm volatile ("inl %w1, %0" : "=a" (val
) : "d" (addr
));
109 static inline uint16_t inw(int addr
)
112 asm volatile ("inw %w1, %w0" : "=a" (val
) : "d" (addr
));
116 static inline uint8_t inb(int addr
)
119 asm volatile ("inb %w1, %b0" : "=a" (val
) : "d" (addr
));
123 static inline void writel(void *addr
, uint32_t val
)
125 *(volatile uint32_t *)addr
= val
;
128 static inline void writew(void *addr
, uint16_t val
)
130 *(volatile uint16_t *)addr
= val
;
133 static inline void writeb(void *addr
, uint8_t val
)
135 *(volatile uint8_t *)addr
= val
;
138 static inline uint32_t readl(const void *addr
)
140 return *(volatile const uint32_t *)addr
;
143 static inline uint16_t readw(const void *addr
)
145 return *(volatile const uint16_t *)addr
;
148 static inline uint8_t readb(const void *addr
)
150 return *(volatile const uint8_t *)addr
;
153 static inline void putc(int c
)
158 static uint64_t rdmsr(unsigned index
)
160 unsigned long long ret
;
162 asm ("rdmsr" : "=A"(ret
) : "c"(index
));
166 static void wrmsr(unsigned index
, uint64_t val
)
168 asm volatile ("wrmsr" : : "c"(index
), "A"(val
));
171 static inline int isdigit(int c
)
173 return c
>= '0' && c
<= '9';
176 void *memset(void *d1
, int val
, size_t len
)
186 void *memcpy(void *d1
, const void *s1
, size_t len
)
189 const uint8_t *s
= s1
;
197 void *memmove(void *d1
, const void *s1
, size_t len
)
200 const uint8_t *s
= s1
;
216 size_t strlen(const char *s
)
219 for(s1
= s
; *s1
!= '\0'; s1
++);
223 /* from BSD ppp sources */
224 int vsnprintf(char *buf
, int buflen
, const char *fmt
, va_list args
)
227 int width
, prec
, fillch
;
229 unsigned long val
= 0;
233 static const char hexchars
[] = "0123456789abcdef";
238 for (f
= fmt
; *f
!= '%' && *f
!= 0; ++f
)
244 memcpy(buf
, fmt
, len
);
259 width
= va_arg(args
, int);
263 width
= width
* 10 + c
- '0';
270 prec
= va_arg(args
, int);
274 prec
= prec
* 10 + c
- '0';
293 i
= va_arg(args
, int);
302 val
= va_arg(args
, unsigned int);
307 val
= va_arg(args
, unsigned int);
311 val
= (unsigned long) va_arg(args
, void *);
316 str
= va_arg(args
, char *);
319 num
[0] = va_arg(args
, int);
326 --fmt
; /* so %z outputs %z etc. */
331 str
= num
+ sizeof(num
);
333 while (str
> num
+ neg
) {
334 *--str
= hexchars
[val
% base
];
336 if (--prec
<= 0 && val
== 0)
348 len
= num
+ sizeof(num
) - 1 - str
;
351 if (prec
> 0 && len
> prec
)
357 if ((n
= width
- len
) > 0) {
365 memcpy(buf
, str
, len
);
373 void bios_printf(int flags
, const char *fmt
, ...)
379 if ((flags
& BIOS_PRINTF_DEBHALT
) == BIOS_PRINTF_DEBHALT
)
380 outb(PANIC_PORT2
, 0x00);
383 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
393 for(i
= 0; i
< n
; i
++) {
395 /* approximative ! */
396 for(j
= 0; j
< 1000000; j
++);
401 r1
= inb(0x61) & 0x10;
403 r2
= inb(0x61) & 0x10;
415 uint32_t cpuid_signature
;
416 uint32_t cpuid_features
;
417 uint32_t cpuid_ext_features
;
418 unsigned long ram_size
;
419 uint64_t above4g_ram_size
;
420 uint8_t bios_uuid
[16];
421 #ifdef BX_USE_EBDA_TABLES
422 unsigned long ebda_cur_addr
;
425 uint32_t pm_io_base
, smb_io_base
;
427 unsigned long bios_table_cur_addr
;
428 unsigned long bios_table_end_addr
;
430 void init_smp_msrs(void)
432 *(uint32_t *)SMP_MSR_ADDR
= 0;
435 void wrmsr_smp(uint32_t index
, uint64_t val
)
437 static struct { uint32_t ecx
, eax
, edx
; } *p
= (void *)SMP_MSR_ADDR
;
447 void uuid_probe(void)
450 uint32_t eax
, ebx
, ecx
, edx
;
452 // check if backdoor port exists
453 asm volatile ("outl %%eax, %%dx"
454 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
455 : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
456 if (ebx
== 0x564d5868) {
457 uint32_t *uuid_ptr
= (uint32_t *)bios_uuid
;
459 asm volatile ("outl %%eax, %%dx"
460 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
461 : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
470 memset(bios_uuid
, 0, 16);
476 uint32_t eax
, ebx
, ecx
, edx
;
477 cpuid(1, eax
, ebx
, ecx
, edx
);
478 cpuid_signature
= eax
;
479 cpuid_features
= edx
;
480 cpuid_ext_features
= ecx
;
483 static int cmos_readb(int addr
)
489 void setup_mtrr(void)
491 int i
, vcnt
, fix
, wc
;
497 uint64_t vbase
, vmask
;
499 mtrr_cap
= rdmsr(MSR_MTRRcap
);
500 vcnt
= mtrr_cap
& 0xff;
501 fix
= mtrr_cap
& 0x100;
502 wc
= mtrr_cap
& 0x400;
506 for (i
= 0; i
< 8; ++i
)
507 if (ram_size
>= 65536 * (i
+ 1))
509 wrmsr_smp(MSR_MTRRfix64K_00000
, u
.val
);
511 for (i
= 0; i
< 8; ++i
)
512 if (ram_size
>= 65536 * 8 + 16384 * (i
+ 1))
514 wrmsr_smp(MSR_MTRRfix16K_80000
, u
.val
);
515 wrmsr_smp(MSR_MTRRfix16K_A0000
, 0);
516 wrmsr_smp(MSR_MTRRfix4K_C0000
, 0);
517 wrmsr_smp(MSR_MTRRfix4K_C8000
, 0);
518 wrmsr_smp(MSR_MTRRfix4K_D0000
, 0);
519 wrmsr_smp(MSR_MTRRfix4K_D8000
, 0);
520 wrmsr_smp(MSR_MTRRfix4K_E0000
, 0);
521 wrmsr_smp(MSR_MTRRfix4K_E8000
, 0);
522 wrmsr_smp(MSR_MTRRfix4K_F0000
, 0);
523 wrmsr_smp(MSR_MTRRfix4K_F8000
, 0);
525 --vcnt
; /* leave one mtrr for VRAM */
526 for (i
= 0; i
< vcnt
&& vbase
< ram_size
; ++i
) {
527 vmask
= (1ull << 40) - 1;
528 while (vbase
+ vmask
+ 1 > ram_size
)
530 wrmsr_smp(MTRRphysBase_MSR(i
), vbase
| 6);
531 wrmsr_smp(MTRRphysMask_MSR(i
), (~vmask
& 0xfffffff000ull
) | 0x800);
534 for (vbase
= 1ull << 32; i
< vcnt
&& vbase
< above4g_ram_size
; ++i
) {
535 vmask
= (1ull << 40) - 1;
536 while (vbase
+ vmask
+ 1 > above4g_ram_size
)
538 wrmsr_smp(MTRRphysBase_MSR(i
), vbase
| 6);
539 wrmsr_smp(MTRRphysMask_MSR(i
), (~vmask
& 0xfffffff000ull
) | 0x800);
542 wrmsr_smp(MSR_MTRRdefType
, 0xc00);
547 if (cmos_readb(0x34) | cmos_readb(0x35))
548 ram_size
= (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
551 ram_size
= (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
553 if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
554 above4g_ram_size
= ((uint64_t)cmos_readb(0x5b) << 16) |
555 ((uint64_t)cmos_readb(0x5c) << 24) | ((uint64_t)cmos_readb(0x5d) << 32);
557 if (above4g_ram_size
)
558 above4g_ram_size
+= 1ull << 32;
560 #ifdef BX_USE_EBDA_TABLES
561 ebda_cur_addr
= ((*(uint16_t *)(0x40e)) << 4) + 0x380;
563 BX_INFO("ram_size=0x%08lx\n", ram_size
);
564 BX_INFO("top of ram %ldMB\n", above4g_ram_size
>> 20);
568 /****************************************************/
571 extern uint8_t smp_ap_boot_code_start
;
572 extern uint8_t smp_ap_boot_code_end
;
574 /* find the number of CPUs by launching a SIPI to them */
577 uint32_t val
, sipi_vector
;
580 if (cpuid_features
& CPUID_APIC
) {
582 /* enable local APIC */
583 val
= readl(APIC_BASE
+ APIC_SVR
);
585 writel(APIC_BASE
+ APIC_SVR
, val
);
587 writew((void *)CPU_COUNT_ADDR
, 1);
588 /* copy AP boot code */
589 memcpy((void *)AP_BOOT_ADDR
, &smp_ap_boot_code_start
,
590 &smp_ap_boot_code_end
- &smp_ap_boot_code_start
);
593 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4500);
594 sipi_vector
= AP_BOOT_ADDR
>> 12;
595 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4600 | sipi_vector
);
597 "xor %%eax, %%eax \n\t"
598 "xor %%edx, %%edx \n\t"
599 "mov $0x10, %%ecx \n\t"
601 : : : "eax", "ecx", "edx");
606 while (cmos_readb(0x5f) + 1 != readw((void *)CPU_COUNT_ADDR
))
610 smp_cpus
= readw((void *)CPU_COUNT_ADDR
);
612 BX_INFO("Found %d cpu(s)\n", smp_cpus
);
615 /****************************************************/
618 #define PCI_ADDRESS_SPACE_MEM 0x00
619 #define PCI_ADDRESS_SPACE_IO 0x01
620 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
622 #define PCI_ROM_SLOT 6
623 #define PCI_NUM_REGIONS 7
625 #define PCI_DEVICES_MAX 64
627 #define PCI_VENDOR_ID 0x00 /* 16 bits */
628 #define PCI_DEVICE_ID 0x02 /* 16 bits */
629 #define PCI_COMMAND 0x04 /* 16 bits */
630 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
631 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
632 #define PCI_CLASS_DEVICE 0x0a /* Device class */
633 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
634 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
635 #define PCI_MIN_GNT 0x3e /* 8 bits */
636 #define PCI_MAX_LAT 0x3f /* 8 bits */
638 typedef struct PCIDevice
{
643 static uint32_t pci_bios_io_addr
;
644 static uint32_t pci_bios_mem_addr
;
645 static uint32_t pci_bios_bigmem_addr
;
646 /* host irqs corresponding to PCI irqs A-D */
647 static uint8_t pci_irqs
[4] = { 10, 10, 11, 11 };
648 static PCIDevice i440_pcidev
;
650 static void pci_config_writel(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
652 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
656 static void pci_config_writew(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
658 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
659 outw(0xcfc + (addr
& 2), val
);
662 static void pci_config_writeb(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
664 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
665 outb(0xcfc + (addr
& 3), val
);
668 static uint32_t pci_config_readl(PCIDevice
*d
, uint32_t addr
)
670 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
674 static uint32_t pci_config_readw(PCIDevice
*d
, uint32_t addr
)
676 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
677 return inw(0xcfc + (addr
& 2));
680 static uint32_t pci_config_readb(PCIDevice
*d
, uint32_t addr
)
682 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
683 return inb(0xcfc + (addr
& 3));
686 static void pci_set_io_region_addr(PCIDevice
*d
, int region_num
, uint32_t addr
)
689 uint32_t ofs
, old_addr
;
691 if ( region_num
== PCI_ROM_SLOT
) {
694 ofs
= 0x10 + region_num
* 4;
697 old_addr
= pci_config_readl(d
, ofs
);
699 pci_config_writel(d
, ofs
, addr
);
700 BX_INFO("region %d: 0x%08x\n", region_num
, addr
);
702 /* enable memory mappings */
703 cmd
= pci_config_readw(d
, PCI_COMMAND
);
704 if ( region_num
== PCI_ROM_SLOT
)
706 else if (old_addr
& PCI_ADDRESS_SPACE_IO
)
710 pci_config_writew(d
, PCI_COMMAND
, cmd
);
713 /* return the global irq number corresponding to a given device irq
714 pin. We could also use the bus number to have a more precise
716 static int pci_slot_get_pirq(PCIDevice
*pci_dev
, int irq_num
)
719 slot_addend
= (pci_dev
->devfn
>> 3) - 1;
720 return (irq_num
+ slot_addend
) & 3;
723 static int find_bios_table_area(void)
726 for(addr
= 0xf0000; addr
< 0x100000; addr
+= 16) {
727 if (*(uint32_t *)addr
== 0xaafb4442) {
728 bios_table_cur_addr
= addr
+ 8;
729 bios_table_end_addr
= bios_table_cur_addr
+ *(uint32_t *)(addr
+ 4);
730 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
731 bios_table_cur_addr
, bios_table_end_addr
);
738 static void bios_shadow_init(PCIDevice
*d
)
742 if (find_bios_table_area() < 0)
745 /* remap the BIOS to shadow RAM an keep it read/write while we
746 are writing tables */
747 v
= pci_config_readb(d
, 0x59);
749 pci_config_writeb(d
, 0x59, v
);
750 memcpy((void *)BIOS_TMP_STORAGE
, (void *)0x000f0000, 0x10000);
752 pci_config_writeb(d
, 0x59, v
);
753 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE
, 0x10000);
758 static void bios_lock_shadow_ram(void)
760 PCIDevice
*d
= &i440_pcidev
;
764 v
= pci_config_readb(d
, 0x59);
765 v
= (v
& 0x0f) | (0x10);
766 pci_config_writeb(d
, 0x59, v
);
769 static void pci_bios_init_bridges(PCIDevice
*d
)
771 uint16_t vendor_id
, device_id
;
773 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
774 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
776 if (vendor_id
== 0x8086 && device_id
== 0x7000) {
784 for(i
= 0; i
< 4; i
++) {
786 /* set to trigger level */
787 elcr
[irq
>> 3] |= (1 << (irq
& 7));
788 /* activate irq remapping in PIIX */
789 pci_config_writeb(d
, 0x60 + i
, irq
);
791 outb(0x4d0, elcr
[0]);
792 outb(0x4d1, elcr
[1]);
793 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
795 } else if (vendor_id
== 0x8086 && device_id
== 0x1237) {
796 /* i440 PCI bridge */
801 extern uint8_t smm_relocation_start
, smm_relocation_end
;
802 extern uint8_t smm_code_start
, smm_code_end
;
805 static void smm_init(PCIDevice
*d
)
809 /* check if SMM init is already done */
810 value
= pci_config_readl(d
, 0x58);
811 if ((value
& (1 << 25)) == 0) {
813 /* copy the SMM relocation code */
814 memcpy((void *)0x38000, &smm_relocation_start
,
815 &smm_relocation_end
- &smm_relocation_start
);
817 /* enable SMI generation when writing to the APMC register */
818 pci_config_writel(d
, 0x58, value
| (1 << 25));
820 /* init APM status port */
823 /* raise an SMI interrupt */
826 /* wait until SMM code executed */
827 while (inb(0xb3) != 0x00);
829 /* enable the SMM memory window */
830 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x48);
832 /* copy the SMM code */
833 memcpy((void *)0xa8000, &smm_code_start
,
834 &smm_code_end
- &smm_code_start
);
837 /* close the SMM memory window and enable normal SMM */
838 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x08);
843 static void pci_bios_init_device(PCIDevice
*d
)
847 int i
, pin
, pic_irq
, vendor_id
, device_id
;
849 class = pci_config_readw(d
, PCI_CLASS_DEVICE
);
850 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
851 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
852 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
853 d
->bus
, d
->devfn
, vendor_id
, device_id
);
856 if (vendor_id
== 0x8086 && device_id
== 0x7010) {
858 pci_config_writew(d
, 0x40, 0x8000); // enable IDE0
859 pci_config_writew(d
, 0x42, 0x8000); // enable IDE1
862 /* IDE: we map it as in ISA mode */
863 pci_set_io_region_addr(d
, 0, 0x1f0);
864 pci_set_io_region_addr(d
, 1, 0x3f4);
865 pci_set_io_region_addr(d
, 2, 0x170);
866 pci_set_io_region_addr(d
, 3, 0x374);
870 if (vendor_id
!= 0x1234)
872 /* VGA: map frame buffer to default Bochs VBE address */
873 pci_set_io_region_addr(d
, 0, 0xE0000000);
877 if (vendor_id
== 0x1014) {
879 if (device_id
== 0x0046 || device_id
== 0xFFFF) {
881 pci_set_io_region_addr(d
, 0, 0x80800000 + 0x00040000);
886 if (vendor_id
== 0x0106b &&
887 (device_id
== 0x0017 || device_id
== 0x0022)) {
889 pci_set_io_region_addr(d
, 0, 0x80800000);
894 /* default memory mappings */
895 for(i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
899 if (i
== PCI_ROM_SLOT
)
903 pci_config_writel(d
, ofs
, 0xffffffff);
904 val
= pci_config_readl(d
, ofs
);
906 size
= (~(val
& ~0xf)) + 1;
907 if (val
& PCI_ADDRESS_SPACE_IO
)
908 paddr
= &pci_bios_io_addr
;
909 else if (size
>= 0x04000000)
910 paddr
= &pci_bios_bigmem_addr
;
912 paddr
= &pci_bios_mem_addr
;
913 *paddr
= (*paddr
+ size
- 1) & ~(size
- 1);
914 pci_set_io_region_addr(d
, i
, *paddr
);
921 /* map the interrupt */
922 pin
= pci_config_readb(d
, PCI_INTERRUPT_PIN
);
924 pin
= pci_slot_get_pirq(d
, pin
- 1);
925 pic_irq
= pci_irqs
[pin
];
926 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, pic_irq
);
929 if (vendor_id
== 0x8086 && device_id
== 0x7113) {
930 /* PIIX4 Power Management device (for ACPI) */
932 // acpi sci is hardwired to 9
933 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, 9);
935 pm_io_base
= PM_IO_BASE
;
936 pci_config_writel(d
, 0x40, pm_io_base
| 1);
937 pci_config_writeb(d
, 0x80, 0x01); /* enable PM io space */
938 smb_io_base
= SMB_IO_BASE
;
939 pci_config_writel(d
, 0x90, smb_io_base
| 1);
940 pci_config_writeb(d
, 0xd2, 0x09); /* enable SMBus io space */
941 pm_sci_int
= pci_config_readb(d
, PCI_INTERRUPT_LINE
);
949 void pci_for_each_device(void (*init_func
)(PCIDevice
*d
))
951 PCIDevice d1
, *d
= &d1
;
953 uint16_t vendor_id
, device_id
;
955 for(bus
= 0; bus
< 1; bus
++) {
956 for(devfn
= 0; devfn
< 256; devfn
++) {
959 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
960 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
961 if (vendor_id
!= 0xffff || device_id
!= 0xffff) {
968 void pci_bios_init(void)
970 pci_bios_io_addr
= 0xc000;
971 pci_bios_mem_addr
= 0xf0000000;
972 pci_bios_bigmem_addr
= ram_size
;
973 if (pci_bios_bigmem_addr
< 0x90000000)
974 pci_bios_bigmem_addr
= 0x90000000;
976 pci_for_each_device(pci_bios_init_bridges
);
978 pci_for_each_device(pci_bios_init_device
);
981 /****************************************************/
982 /* Multi Processor table init */
984 static void putb(uint8_t **pp
, int val
)
992 static void putstr(uint8_t **pp
, const char *str
)
1001 static void putle16(uint8_t **pp
, int val
)
1010 static void putle32(uint8_t **pp
, int val
)
1021 static int mpf_checksum(const uint8_t *data
, int len
)
1025 for(i
= 0; i
< len
; i
++)
1030 static unsigned long align(unsigned long addr
, unsigned long v
)
1032 return (addr
+ v
- 1) & ~(v
- 1);
1035 static void mptable_init(void)
1037 uint8_t *mp_config_table
, *q
, *float_pointer_struct
;
1038 int ioapic_id
, i
, len
;
1039 int mp_config_table_size
;
1041 #ifdef BX_USE_EBDA_TABLES
1042 mp_config_table
= (uint8_t *)(ram_size
- ACPI_DATA_SIZE
- MPTABLE_MAX_SIZE
);
1044 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1045 mp_config_table
= (uint8_t *)bios_table_cur_addr
;
1047 q
= mp_config_table
;
1048 putstr(&q
, "PCMP"); /* "PCMP signature */
1049 putle16(&q
, 0); /* table length (patched later) */
1050 putb(&q
, 4); /* spec rev */
1051 putb(&q
, 0); /* checksum (patched later) */
1053 putstr(&q
, "QEMUCPU "); /* OEM id */
1055 putstr(&q
, "BOCHSCPU");
1057 putstr(&q
, "0.1 "); /* vendor id */
1058 putle32(&q
, 0); /* OEM table ptr */
1059 putle16(&q
, 0); /* OEM table size */
1060 putle16(&q
, MAX_CPUS
+ 18); /* entry count */
1061 putle32(&q
, 0xfee00000); /* local APIC addr */
1062 putle16(&q
, 0); /* ext table length */
1063 putb(&q
, 0); /* ext table checksum */
1064 putb(&q
, 0); /* reserved */
1066 for(i
= 0; i
< MAX_CPUS
; i
++) {
1067 putb(&q
, 0); /* entry type = processor */
1068 putb(&q
, i
); /* APIC id */
1069 putb(&q
, 0x11); /* local APIC version number */
1071 putb(&q
, 3); /* cpu flags: enabled, bootstrap cpu */
1072 else if ( i
< smp_cpus
)
1073 putb(&q
, 1); /* cpu flags: enabled */
1075 putb(&q
, 0); /* cpu flags: disabled */
1076 putb(&q
, 0); /* cpu signature */
1080 putle16(&q
, 0x201); /* feature flags */
1083 putle16(&q
, 0); /* reserved */
1090 putb(&q
, 1); /* entry type = bus */
1091 putb(&q
, 0); /* bus ID */
1095 ioapic_id
= smp_cpus
;
1096 putb(&q
, 2); /* entry type = I/O APIC */
1097 putb(&q
, ioapic_id
); /* apic ID */
1098 putb(&q
, 0x11); /* I/O APIC version number */
1099 putb(&q
, 1); /* enable */
1100 putle32(&q
, 0xfec00000); /* I/O APIC addr */
1103 for(i
= 0; i
< 16; i
++) {
1104 putb(&q
, 3); /* entry type = I/O interrupt */
1105 putb(&q
, 0); /* interrupt type = vectored interrupt */
1106 putb(&q
, 0); /* flags: po=0, el=0 */
1108 putb(&q
, 0); /* source bus ID = ISA */
1109 putb(&q
, i
); /* source bus IRQ */
1110 putb(&q
, ioapic_id
); /* dest I/O APIC ID */
1111 putb(&q
, i
); /* dest I/O APIC interrupt in */
1114 len
= q
- mp_config_table
;
1115 mp_config_table
[4] = len
;
1116 mp_config_table
[5] = len
>> 8;
1118 mp_config_table
[7] = -mpf_checksum(mp_config_table
, q
- mp_config_table
);
1120 mp_config_table_size
= q
- mp_config_table
;
1122 #ifndef BX_USE_EBDA_TABLES
1123 bios_table_cur_addr
+= mp_config_table_size
;
1126 /* floating pointer structure */
1127 #ifdef BX_USE_EBDA_TABLES
1128 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1129 float_pointer_struct
= (uint8_t *)ebda_cur_addr
;
1131 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1132 float_pointer_struct
= (uint8_t *)bios_table_cur_addr
;
1134 q
= float_pointer_struct
;
1136 /* pointer to MP config table */
1137 putle32(&q
, (unsigned long)mp_config_table
);
1139 putb(&q
, 1); /* length in 16 byte units */
1140 putb(&q
, 4); /* MP spec revision */
1141 putb(&q
, 0); /* checksum (patched later) */
1142 putb(&q
, 0); /* MP feature byte 1 */
1148 float_pointer_struct
[10] =
1149 -mpf_checksum(float_pointer_struct
, q
- float_pointer_struct
);
1150 #ifdef BX_USE_EBDA_TABLES
1151 ebda_cur_addr
+= (q
- float_pointer_struct
);
1153 bios_table_cur_addr
+= (q
- float_pointer_struct
);
1155 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
1156 (unsigned long)float_pointer_struct
,
1157 (unsigned long)mp_config_table
,
1158 mp_config_table_size
);
1161 /****************************************************/
1162 /* ACPI tables init */
1164 /* Table structure from Linux kernel (the ACPI tables are under the
1167 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
1168 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
1169 uint32_t length; /* Length of table, in bytes, including header */\
1170 uint8_t revision; /* ACPI Specification minor version # */\
1171 uint8_t checksum; /* To make sum of entire table == 0 */\
1172 uint8_t oem_id [6]; /* OEM identification */\
1173 uint8_t oem_table_id [8]; /* OEM table identification */\
1174 uint32_t oem_revision; /* OEM revision number */\
1175 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
1176 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1179 struct acpi_table_header
/* ACPI common table header */
1181 ACPI_TABLE_HEADER_DEF
1184 struct rsdp_descriptor
/* Root System Descriptor Pointer */
1186 uint8_t signature
[8]; /* ACPI signature, contains "RSD PTR " */
1187 uint8_t checksum
; /* To make sum of struct == 0 */
1188 uint8_t oem_id
[6]; /* OEM identification */
1189 uint8_t revision
; /* Must be 0 for 1.0, 2 for 2.0 */
1190 uint32_t rsdt_physical_address
; /* 32-bit physical address of RSDT */
1191 uint32_t length
; /* XSDT Length in bytes including hdr */
1192 uint64_t xsdt_physical_address
; /* 64-bit physical address of XSDT */
1193 uint8_t extended_checksum
; /* Checksum of entire table */
1194 uint8_t reserved
[3]; /* Reserved field must be 0 */
1198 * ACPI 1.0 Root System Description Table (RSDT)
1200 struct rsdt_descriptor_rev1
1202 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1203 uint32_t table_offset_entry
[2]; /* Array of pointers to other */
1208 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1210 struct facs_descriptor_rev1
1212 uint8_t signature
[4]; /* ACPI Signature */
1213 uint32_t length
; /* Length of structure, in bytes */
1214 uint32_t hardware_signature
; /* Hardware configuration signature */
1215 uint32_t firmware_waking_vector
; /* ACPI OS waking vector */
1216 uint32_t global_lock
; /* Global Lock */
1217 uint32_t S4bios_f
: 1; /* Indicates if S4BIOS support is present */
1218 uint32_t reserved1
: 31; /* Must be 0 */
1219 uint8_t resverved3
[40]; /* Reserved - must be zero */
1224 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1226 struct fadt_descriptor_rev1
1228 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1229 uint32_t firmware_ctrl
; /* Physical address of FACS */
1230 uint32_t dsdt
; /* Physical address of DSDT */
1231 uint8_t model
; /* System Interrupt Model */
1232 uint8_t reserved1
; /* Reserved */
1233 uint16_t sci_int
; /* System vector of SCI interrupt */
1234 uint32_t smi_cmd
; /* Port address of SMI command port */
1235 uint8_t acpi_enable
; /* Value to write to smi_cmd to enable ACPI */
1236 uint8_t acpi_disable
; /* Value to write to smi_cmd to disable ACPI */
1237 uint8_t S4bios_req
; /* Value to write to SMI CMD to enter S4BIOS state */
1238 uint8_t reserved2
; /* Reserved - must be zero */
1239 uint32_t pm1a_evt_blk
; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1240 uint32_t pm1b_evt_blk
; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1241 uint32_t pm1a_cnt_blk
; /* Port address of Power Mgt 1a Control Reg Blk */
1242 uint32_t pm1b_cnt_blk
; /* Port address of Power Mgt 1b Control Reg Blk */
1243 uint32_t pm2_cnt_blk
; /* Port address of Power Mgt 2 Control Reg Blk */
1244 uint32_t pm_tmr_blk
; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1245 uint32_t gpe0_blk
; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1246 uint32_t gpe1_blk
; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1247 uint8_t pm1_evt_len
; /* Byte length of ports at pm1_x_evt_blk */
1248 uint8_t pm1_cnt_len
; /* Byte length of ports at pm1_x_cnt_blk */
1249 uint8_t pm2_cnt_len
; /* Byte Length of ports at pm2_cnt_blk */
1250 uint8_t pm_tmr_len
; /* Byte Length of ports at pm_tm_blk */
1251 uint8_t gpe0_blk_len
; /* Byte Length of ports at gpe0_blk */
1252 uint8_t gpe1_blk_len
; /* Byte Length of ports at gpe1_blk */
1253 uint8_t gpe1_base
; /* Offset in gpe model where gpe1 events start */
1254 uint8_t reserved3
; /* Reserved */
1255 uint16_t plvl2_lat
; /* Worst case HW latency to enter/exit C2 state */
1256 uint16_t plvl3_lat
; /* Worst case HW latency to enter/exit C3 state */
1257 uint16_t flush_size
; /* Size of area read to flush caches */
1258 uint16_t flush_stride
; /* Stride used in flushing caches */
1259 uint8_t duty_offset
; /* Bit location of duty cycle field in p_cnt reg */
1260 uint8_t duty_width
; /* Bit width of duty cycle field in p_cnt reg */
1261 uint8_t day_alrm
; /* Index to day-of-month alarm in RTC CMOS RAM */
1262 uint8_t mon_alrm
; /* Index to month-of-year alarm in RTC CMOS RAM */
1263 uint8_t century
; /* Index to century in RTC CMOS RAM */
1264 uint8_t reserved4
; /* Reserved */
1265 uint8_t reserved4a
; /* Reserved */
1266 uint8_t reserved4b
; /* Reserved */
1268 uint32_t wb_invd
: 1; /* The wbinvd instruction works properly */
1269 uint32_t wb_invd_flush
: 1; /* The wbinvd flushes but does not invalidate */
1270 uint32_t proc_c1
: 1; /* All processors support C1 state */
1271 uint32_t plvl2_up
: 1; /* C2 state works on MP system */
1272 uint32_t pwr_button
: 1; /* Power button is handled as a generic feature */
1273 uint32_t sleep_button
: 1; /* Sleep button is handled as a generic feature, or not present */
1274 uint32_t fixed_rTC
: 1; /* RTC wakeup stat not in fixed register space */
1275 uint32_t rtcs4
: 1; /* RTC wakeup stat not possible from S4 */
1276 uint32_t tmr_val_ext
: 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1277 uint32_t reserved5
: 23; /* Reserved - must be zero */
1284 * MADT values and structures
1287 /* Values for MADT PCATCompat */
1290 #define MULTIPLE_APIC 1
1295 struct multiple_apic_table
1297 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1298 uint32_t local_apic_address
; /* Physical address of local APIC */
1300 uint32_t PCATcompat
: 1; /* A one indicates system also has dual 8259s */
1301 uint32_t reserved1
: 31;
1308 /* Values for Type in APIC_HEADER_DEF */
1310 #define APIC_PROCESSOR 0
1312 #define APIC_XRUPT_OVERRIDE 2
1314 #define APIC_LOCAL_NMI 4
1315 #define APIC_ADDRESS_OVERRIDE 5
1316 #define APIC_IO_SAPIC 6
1317 #define APIC_LOCAL_SAPIC 7
1318 #define APIC_XRUPT_SOURCE 8
1319 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1322 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1324 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1328 /* Sub-structures for MADT */
1330 struct madt_processor_apic
1333 uint8_t processor_id
; /* ACPI processor id */
1334 uint8_t local_apic_id
; /* Processor's local APIC id */
1336 uint32_t processor_enabled
: 1; /* Processor is usable if set */
1337 uint32_t reserved2
: 31; /* Reserved, must be zero */
1346 uint8_t io_apic_id
; /* I/O APIC ID */
1347 uint8_t reserved
; /* Reserved - must be zero */
1348 uint32_t address
; /* APIC physical address */
1349 uint32_t interrupt
; /* Global system interrupt where INTI
1353 struct madt_intsrcovr
{
1359 } __attribute__((packed
));
1361 #include "acpi-dsdt.hex"
1363 static inline uint16_t cpu_to_le16(uint16_t x
)
1368 static inline uint32_t cpu_to_le32(uint32_t x
)
1373 static int acpi_checksum(const uint8_t *data
, int len
)
1377 for(i
= 0; i
< len
; i
++)
1379 return (-sum
) & 0xff;
1382 static void acpi_build_table_header(struct acpi_table_header
*h
,
1383 char *sig
, int len
, uint8_t rev
)
1385 memcpy(h
->signature
, sig
, 4);
1386 h
->length
= cpu_to_le32(len
);
1389 memcpy(h
->oem_id
, "QEMU ", 6);
1390 memcpy(h
->oem_table_id
, "QEMU", 4);
1392 memcpy(h
->oem_id
, "BOCHS ", 6);
1393 memcpy(h
->oem_table_id
, "BXPC", 4);
1395 memcpy(h
->oem_table_id
+ 4, sig
, 4);
1396 h
->oem_revision
= cpu_to_le32(1);
1398 memcpy(h
->asl_compiler_id
, "QEMU", 4);
1400 memcpy(h
->asl_compiler_id
, "BXPC", 4);
1402 h
->asl_compiler_revision
= cpu_to_le32(1);
1403 h
->checksum
= acpi_checksum((void *)h
, len
);
1406 /* base_addr must be a multiple of 4KB */
1407 void acpi_bios_init(void)
1409 struct rsdp_descriptor
*rsdp
;
1410 struct rsdt_descriptor_rev1
*rsdt
;
1411 struct fadt_descriptor_rev1
*fadt
;
1412 struct facs_descriptor_rev1
*facs
;
1413 struct multiple_apic_table
*madt
;
1415 uint32_t base_addr
, rsdt_addr
, fadt_addr
, addr
, facs_addr
, dsdt_addr
;
1416 uint32_t acpi_tables_size
, madt_addr
, madt_size
;
1419 /* reserve memory space for tables */
1420 #ifdef BX_USE_EBDA_TABLES
1421 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1422 rsdp
= (void *)(ebda_cur_addr
);
1423 ebda_cur_addr
+= sizeof(*rsdp
);
1425 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1426 rsdp
= (void *)(bios_table_cur_addr
);
1427 bios_table_cur_addr
+= sizeof(*rsdp
);
1430 addr
= base_addr
= ram_size
- ACPI_DATA_SIZE
;
1432 rsdt
= (void *)(addr
);
1433 addr
+= sizeof(*rsdt
);
1436 fadt
= (void *)(addr
);
1437 addr
+= sizeof(*fadt
);
1439 /* XXX: FACS should be in RAM */
1440 addr
= (addr
+ 63) & ~63; /* 64 byte alignment for FACS */
1442 facs
= (void *)(addr
);
1443 addr
+= sizeof(*facs
);
1446 dsdt
= (void *)(addr
);
1447 addr
+= sizeof(AmlCode
);
1449 addr
= (addr
+ 7) & ~7;
1451 madt_size
= sizeof(*madt
) +
1452 sizeof(struct madt_processor_apic
) * MAX_CPUS
+
1453 sizeof(struct madt_io_apic
);
1454 madt
= (void *)(addr
);
1457 acpi_tables_size
= addr
- base_addr
;
1459 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1460 (unsigned long)rsdp
,
1461 (unsigned long)rsdt
, acpi_tables_size
);
1464 memset(rsdp
, 0, sizeof(*rsdp
));
1465 memcpy(rsdp
->signature
, "RSD PTR ", 8);
1467 memcpy(rsdp
->oem_id
, "QEMU ", 6);
1469 memcpy(rsdp
->oem_id
, "BOCHS ", 6);
1471 rsdp
->rsdt_physical_address
= cpu_to_le32(rsdt_addr
);
1472 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
1475 memset(rsdt
, 0, sizeof(*rsdt
));
1476 rsdt
->table_offset_entry
[0] = cpu_to_le32(fadt_addr
);
1477 rsdt
->table_offset_entry
[1] = cpu_to_le32(madt_addr
);
1478 acpi_build_table_header((struct acpi_table_header
*)rsdt
,
1479 "RSDT", sizeof(*rsdt
), 1);
1482 memset(fadt
, 0, sizeof(*fadt
));
1483 fadt
->firmware_ctrl
= cpu_to_le32(facs_addr
);
1484 fadt
->dsdt
= cpu_to_le32(dsdt_addr
);
1486 fadt
->reserved1
= 0;
1487 fadt
->sci_int
= cpu_to_le16(pm_sci_int
);
1488 fadt
->smi_cmd
= cpu_to_le32(SMI_CMD_IO_ADDR
);
1489 fadt
->acpi_enable
= 0xf1;
1490 fadt
->acpi_disable
= 0xf0;
1491 fadt
->pm1a_evt_blk
= cpu_to_le32(pm_io_base
);
1492 fadt
->pm1a_cnt_blk
= cpu_to_le32(pm_io_base
+ 0x04);
1493 fadt
->pm_tmr_blk
= cpu_to_le32(pm_io_base
+ 0x08);
1494 fadt
->pm1_evt_len
= 4;
1495 fadt
->pm1_cnt_len
= 2;
1496 fadt
->pm_tmr_len
= 4;
1497 fadt
->plvl2_lat
= cpu_to_le16(0x0fff); // C2 state not supported
1498 fadt
->plvl3_lat
= cpu_to_le16(0x0fff); // C3 state not supported
1499 fadt
->gpe0_blk
= cpu_to_le32(0xafe0);
1500 fadt
->gpe0_blk_len
= 4;
1501 /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
1502 fadt
->flags
= cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
1503 acpi_build_table_header((struct acpi_table_header
*)fadt
, "FACP",
1507 memset(facs
, 0, sizeof(*facs
));
1508 memcpy(facs
->signature
, "FACS", 4);
1509 facs
->length
= cpu_to_le32(sizeof(*facs
));
1512 memcpy(dsdt
, AmlCode
, sizeof(AmlCode
));
1516 struct madt_processor_apic
*apic
;
1517 struct madt_io_apic
*io_apic
;
1518 struct madt_intsrcovr
*intsrcovr
;
1520 memset(madt
, 0, madt_size
);
1521 madt
->local_apic_address
= cpu_to_le32(0xfee00000);
1522 madt
->flags
= cpu_to_le32(1);
1523 apic
= (void *)(madt
+ 1);
1524 for(i
=0;i
<MAX_CPUS
;i
++) {
1525 apic
->type
= APIC_PROCESSOR
;
1526 apic
->length
= sizeof(*apic
);
1527 apic
->processor_id
= i
;
1528 apic
->local_apic_id
= i
;
1530 apic
->flags
= cpu_to_le32(1);
1535 io_apic
= (void *)apic
;
1536 io_apic
->type
= APIC_IO
;
1537 io_apic
->length
= sizeof(*io_apic
);
1538 io_apic
->io_apic_id
= smp_cpus
;
1539 io_apic
->address
= cpu_to_le32(0xfec00000);
1540 io_apic
->interrupt
= cpu_to_le32(0);
1542 intsrcovr
= (struct madt_intsrcovr
*)(io_apic
+ 1);
1543 for ( i
= 0; i
< 16; i
++ ) {
1544 if ( PCI_ISA_IRQ_MASK
& (1U << i
) ) {
1545 memset(intsrcovr
, 0, sizeof(*intsrcovr
));
1546 intsrcovr
->type
= APIC_XRUPT_OVERRIDE
;
1547 intsrcovr
->length
= sizeof(*intsrcovr
);
1548 intsrcovr
->source
= i
;
1550 intsrcovr
->flags
= 0xd; /* active high, level triggered */
1552 /* No need for a INT source override structure. */
1556 madt_size
+= sizeof(struct madt_intsrcovr
);
1558 acpi_build_table_header((struct acpi_table_header
*)madt
,
1559 "APIC", madt_size
, 1);
1563 /* SMBIOS entry point -- must be written to a 16-bit aligned address
1564 between 0xf0000 and 0xfffff.
1566 struct smbios_entry_point
{
1567 char anchor_string
[4];
1570 uint8_t smbios_major_version
;
1571 uint8_t smbios_minor_version
;
1572 uint16_t max_structure_size
;
1573 uint8_t entry_point_revision
;
1574 uint8_t formatted_area
[5];
1575 char intermediate_anchor_string
[5];
1576 uint8_t intermediate_checksum
;
1577 uint16_t structure_table_length
;
1578 uint32_t structure_table_address
;
1579 uint16_t number_of_structures
;
1580 uint8_t smbios_bcd_revision
;
1581 } __attribute__((__packed__
));
1583 /* This goes at the beginning of every SMBIOS structure. */
1584 struct smbios_structure_header
{
1588 } __attribute__((__packed__
));
1590 /* SMBIOS type 0 - BIOS Information */
1591 struct smbios_type_0
{
1592 struct smbios_structure_header header
;
1594 uint8_t bios_version_str
;
1595 uint16_t bios_starting_address_segment
;
1596 uint8_t bios_release_date_str
;
1597 uint8_t bios_rom_size
;
1598 uint8_t bios_characteristics
[8];
1599 uint8_t bios_characteristics_extension_bytes
[2];
1600 uint8_t system_bios_major_release
;
1601 uint8_t system_bios_minor_release
;
1602 uint8_t embedded_controller_major_release
;
1603 uint8_t embedded_controller_minor_release
;
1604 } __attribute__((__packed__
));
1606 /* SMBIOS type 1 - System Information */
1607 struct smbios_type_1
{
1608 struct smbios_structure_header header
;
1609 uint8_t manufacturer_str
;
1610 uint8_t product_name_str
;
1611 uint8_t version_str
;
1612 uint8_t serial_number_str
;
1614 uint8_t wake_up_type
;
1615 uint8_t sku_number_str
;
1617 } __attribute__((__packed__
));
1619 /* SMBIOS type 3 - System Enclosure (v2.3) */
1620 struct smbios_type_3
{
1621 struct smbios_structure_header header
;
1622 uint8_t manufacturer_str
;
1624 uint8_t version_str
;
1625 uint8_t serial_number_str
;
1626 uint8_t asset_tag_number_str
;
1627 uint8_t boot_up_state
;
1628 uint8_t power_supply_state
;
1629 uint8_t thermal_state
;
1630 uint8_t security_status
;
1631 uint32_t oem_defined
;
1633 uint8_t number_of_power_cords
;
1634 uint8_t contained_element_count
;
1635 // contained elements follow
1636 } __attribute__((__packed__
));
1638 /* SMBIOS type 4 - Processor Information (v2.0) */
1639 struct smbios_type_4
{
1640 struct smbios_structure_header header
;
1641 uint8_t socket_designation_str
;
1642 uint8_t processor_type
;
1643 uint8_t processor_family
;
1644 uint8_t processor_manufacturer_str
;
1645 uint32_t processor_id
[2];
1646 uint8_t processor_version_str
;
1648 uint16_t external_clock
;
1650 uint16_t current_speed
;
1652 uint8_t processor_upgrade
;
1653 } __attribute__((__packed__
));
1655 /* SMBIOS type 16 - Physical Memory Array
1656 * Associated with one type 17 (Memory Device).
1658 struct smbios_type_16
{
1659 struct smbios_structure_header header
;
1662 uint8_t error_correction
;
1663 uint32_t maximum_capacity
;
1664 uint16_t memory_error_information_handle
;
1665 uint16_t number_of_memory_devices
;
1666 } __attribute__((__packed__
));
1668 /* SMBIOS type 17 - Memory Device
1669 * Associated with one type 19
1671 struct smbios_type_17
{
1672 struct smbios_structure_header header
;
1673 uint16_t physical_memory_array_handle
;
1674 uint16_t memory_error_information_handle
;
1675 uint16_t total_width
;
1676 uint16_t data_width
;
1678 uint8_t form_factor
;
1680 uint8_t device_locator_str
;
1681 uint8_t bank_locator_str
;
1682 uint8_t memory_type
;
1683 uint16_t type_detail
;
1684 } __attribute__((__packed__
));
1686 /* SMBIOS type 19 - Memory Array Mapped Address */
1687 struct smbios_type_19
{
1688 struct smbios_structure_header header
;
1689 uint32_t starting_address
;
1690 uint32_t ending_address
;
1691 uint16_t memory_array_handle
;
1692 uint8_t partition_width
;
1693 } __attribute__((__packed__
));
1695 /* SMBIOS type 20 - Memory Device Mapped Address */
1696 struct smbios_type_20
{
1697 struct smbios_structure_header header
;
1698 uint32_t starting_address
;
1699 uint32_t ending_address
;
1700 uint16_t memory_device_handle
;
1701 uint16_t memory_array_mapped_address_handle
;
1702 uint8_t partition_row_position
;
1703 uint8_t interleave_position
;
1704 uint8_t interleaved_data_depth
;
1705 } __attribute__((__packed__
));
1707 /* SMBIOS type 32 - System Boot Information */
1708 struct smbios_type_32
{
1709 struct smbios_structure_header header
;
1710 uint8_t reserved
[6];
1711 uint8_t boot_status
;
1712 } __attribute__((__packed__
));
1714 /* SMBIOS type 127 -- End-of-table */
1715 struct smbios_type_127
{
1716 struct smbios_structure_header header
;
1717 } __attribute__((__packed__
));
1720 smbios_entry_point_init(void *start
,
1721 uint16_t max_structure_size
,
1722 uint16_t structure_table_length
,
1723 uint32_t structure_table_address
,
1724 uint16_t number_of_structures
)
1728 struct smbios_entry_point
*ep
= (struct smbios_entry_point
*)start
;
1730 memcpy(ep
->anchor_string
, "_SM_", 4);
1732 ep
->smbios_major_version
= 2;
1733 ep
->smbios_minor_version
= 4;
1734 ep
->max_structure_size
= max_structure_size
;
1735 ep
->entry_point_revision
= 0;
1736 memset(ep
->formatted_area
, 0, 5);
1737 memcpy(ep
->intermediate_anchor_string
, "_DMI_", 5);
1739 ep
->structure_table_length
= structure_table_length
;
1740 ep
->structure_table_address
= structure_table_address
;
1741 ep
->number_of_structures
= number_of_structures
;
1742 ep
->smbios_bcd_revision
= 0x24;
1745 ep
->intermediate_checksum
= 0;
1748 for (i
= 0; i
< 0x10; i
++)
1749 sum
+= ((int8_t *)start
)[i
];
1750 ep
->checksum
= -sum
;
1753 for (i
= 0x10; i
< ep
->length
; i
++)
1754 sum
+= ((int8_t *)start
)[i
];
1755 ep
->intermediate_checksum
= -sum
;
1758 /* Type 0 -- BIOS Information */
1759 #define RELEASE_DATE_STR "01/01/2007"
1761 smbios_type_0_init(void *start
)
1763 struct smbios_type_0
*p
= (struct smbios_type_0
*)start
;
1766 p
->header
.length
= sizeof(struct smbios_type_0
);
1767 p
->header
.handle
= 0;
1770 p
->bios_version_str
= 1;
1771 p
->bios_starting_address_segment
= 0xe800;
1772 p
->bios_release_date_str
= 2;
1773 p
->bios_rom_size
= 0; /* FIXME */
1775 memset(p
->bios_characteristics
, 0, 7);
1776 p
->bios_characteristics
[7] = 0x08; /* BIOS characteristics not supported */
1777 p
->bios_characteristics_extension_bytes
[0] = 0;
1778 p
->bios_characteristics_extension_bytes
[1] = 0;
1780 p
->system_bios_major_release
= 1;
1781 p
->system_bios_minor_release
= 0;
1782 p
->embedded_controller_major_release
= 0xff;
1783 p
->embedded_controller_minor_release
= 0xff;
1785 start
+= sizeof(struct smbios_type_0
);
1786 memcpy((char *)start
, BX_APPNAME
, sizeof(BX_APPNAME
));
1787 start
+= sizeof(BX_APPNAME
);
1788 memcpy((char *)start
, RELEASE_DATE_STR
, sizeof(RELEASE_DATE_STR
));
1789 start
+= sizeof(RELEASE_DATE_STR
);
1790 *((uint8_t *)start
) = 0;
1795 /* Type 1 -- System Information */
1797 smbios_type_1_init(void *start
)
1799 struct smbios_type_1
*p
= (struct smbios_type_1
*)start
;
1801 p
->header
.length
= sizeof(struct smbios_type_1
);
1802 p
->header
.handle
= 0x100;
1804 p
->manufacturer_str
= 0;
1805 p
->product_name_str
= 0;
1807 p
->serial_number_str
= 0;
1809 memcpy(p
->uuid
, bios_uuid
, 16);
1811 p
->wake_up_type
= 0x06; /* power switch */
1812 p
->sku_number_str
= 0;
1815 start
+= sizeof(struct smbios_type_1
);
1816 *((uint16_t *)start
) = 0;
1821 /* Type 3 -- System Enclosure */
1823 smbios_type_3_init(void *start
)
1825 struct smbios_type_3
*p
= (struct smbios_type_3
*)start
;
1828 p
->header
.length
= sizeof(struct smbios_type_3
);
1829 p
->header
.handle
= 0x300;
1831 p
->manufacturer_str
= 0;
1832 p
->type
= 0x01; /* other */
1834 p
->serial_number_str
= 0;
1835 p
->asset_tag_number_str
= 0;
1836 p
->boot_up_state
= 0x03; /* safe */
1837 p
->power_supply_state
= 0x03; /* safe */
1838 p
->thermal_state
= 0x03; /* safe */
1839 p
->security_status
= 0x02; /* unknown */
1842 p
->number_of_power_cords
= 0;
1843 p
->contained_element_count
= 0;
1845 start
+= sizeof(struct smbios_type_3
);
1846 *((uint16_t *)start
) = 0;
1851 /* Type 4 -- Processor Information */
1853 smbios_type_4_init(void *start
, unsigned int cpu_number
)
1855 struct smbios_type_4
*p
= (struct smbios_type_4
*)start
;
1858 p
->header
.length
= sizeof(struct smbios_type_4
);
1859 p
->header
.handle
= 0x400 + cpu_number
;
1861 p
->socket_designation_str
= 1;
1862 p
->processor_type
= 0x03; /* CPU */
1863 p
->processor_family
= 0x01; /* other */
1864 p
->processor_manufacturer_str
= 0;
1866 p
->processor_id
[0] = cpuid_signature
;
1867 p
->processor_id
[1] = cpuid_features
;
1869 p
->processor_version_str
= 0;
1871 p
->external_clock
= 0;
1873 p
->max_speed
= 0; /* unknown */
1874 p
->current_speed
= 0; /* unknown */
1876 p
->status
= 0x41; /* socket populated, CPU enabled */
1877 p
->processor_upgrade
= 0x01; /* other */
1879 start
+= sizeof(struct smbios_type_4
);
1881 memcpy((char *)start
, "CPU " "\0" "" "\0" "", 7);
1882 ((char *)start
)[4] = cpu_number
+ '0';
1887 /* Type 16 -- Physical Memory Array */
1889 smbios_type_16_init(void *start
, uint32_t memsize
)
1891 struct smbios_type_16
*p
= (struct smbios_type_16
*)start
;
1893 p
->header
.type
= 16;
1894 p
->header
.length
= sizeof(struct smbios_type_16
);
1895 p
->header
.handle
= 0x1000;
1897 p
->location
= 0x01; /* other */
1898 p
->use
= 0x03; /* system memory */
1899 p
->error_correction
= 0x01; /* other */
1900 p
->maximum_capacity
= memsize
* 1024;
1901 p
->memory_error_information_handle
= 0xfffe; /* none provided */
1902 p
->number_of_memory_devices
= 1;
1904 start
+= sizeof(struct smbios_type_16
);
1905 *((uint16_t *)start
) = 0;
1910 /* Type 17 -- Memory Device */
1912 smbios_type_17_init(void *start
, uint32_t memory_size_mb
)
1914 struct smbios_type_17
*p
= (struct smbios_type_17
*)start
;
1916 p
->header
.type
= 17;
1917 p
->header
.length
= sizeof(struct smbios_type_17
);
1918 p
->header
.handle
= 0x1100;
1920 p
->physical_memory_array_handle
= 0x1000;
1921 p
->total_width
= 64;
1923 /* truncate memory_size_mb to 16 bits and clear most significant
1924 bit [indicates size in MB] */
1925 p
->size
= (uint16_t) memory_size_mb
& 0x7fff;
1926 p
->form_factor
= 0x09; /* DIMM */
1928 p
->device_locator_str
= 1;
1929 p
->bank_locator_str
= 0;
1930 p
->memory_type
= 0x07; /* RAM */
1933 start
+= sizeof(struct smbios_type_17
);
1934 memcpy((char *)start
, "DIMM 1", 7);
1936 *((uint8_t *)start
) = 0;
1941 /* Type 19 -- Memory Array Mapped Address */
1943 smbios_type_19_init(void *start
, uint32_t memory_size_mb
)
1945 struct smbios_type_19
*p
= (struct smbios_type_19
*)start
;
1947 p
->header
.type
= 19;
1948 p
->header
.length
= sizeof(struct smbios_type_19
);
1949 p
->header
.handle
= 0x1300;
1951 p
->starting_address
= 0;
1952 p
->ending_address
= (memory_size_mb
-1) * 1024;
1953 p
->memory_array_handle
= 0x1000;
1954 p
->partition_width
= 1;
1956 start
+= sizeof(struct smbios_type_19
);
1957 *((uint16_t *)start
) = 0;
1962 /* Type 20 -- Memory Device Mapped Address */
1964 smbios_type_20_init(void *start
, uint32_t memory_size_mb
)
1966 struct smbios_type_20
*p
= (struct smbios_type_20
*)start
;
1968 p
->header
.type
= 20;
1969 p
->header
.length
= sizeof(struct smbios_type_20
);
1970 p
->header
.handle
= 0x1400;
1972 p
->starting_address
= 0;
1973 p
->ending_address
= (memory_size_mb
-1)*1024;
1974 p
->memory_device_handle
= 0x1100;
1975 p
->memory_array_mapped_address_handle
= 0x1300;
1976 p
->partition_row_position
= 1;
1977 p
->interleave_position
= 0;
1978 p
->interleaved_data_depth
= 0;
1980 start
+= sizeof(struct smbios_type_20
);
1982 *((uint16_t *)start
) = 0;
1986 /* Type 32 -- System Boot Information */
1988 smbios_type_32_init(void *start
)
1990 struct smbios_type_32
*p
= (struct smbios_type_32
*)start
;
1992 p
->header
.type
= 32;
1993 p
->header
.length
= sizeof(struct smbios_type_32
);
1994 p
->header
.handle
= 0x2000;
1995 memset(p
->reserved
, 0, 6);
1996 p
->boot_status
= 0; /* no errors detected */
1998 start
+= sizeof(struct smbios_type_32
);
1999 *((uint16_t *)start
) = 0;
2004 /* Type 127 -- End of Table */
2006 smbios_type_127_init(void *start
)
2008 struct smbios_type_127
*p
= (struct smbios_type_127
*)start
;
2010 p
->header
.type
= 127;
2011 p
->header
.length
= sizeof(struct smbios_type_127
);
2012 p
->header
.handle
= 0x7f00;
2014 start
+= sizeof(struct smbios_type_127
);
2015 *((uint16_t *)start
) = 0;
2020 void smbios_init(void)
2022 unsigned cpu_num
, nr_structs
= 0, max_struct_size
= 0;
2023 char *start
, *p
, *q
;
2024 int memsize
= ram_size
/ (1024 * 1024);
2026 #ifdef BX_USE_EBDA_TABLES
2027 ebda_cur_addr
= align(ebda_cur_addr
, 16);
2028 start
= (void *)(ebda_cur_addr
);
2030 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
2031 start
= (void *)(bios_table_cur_addr
);
2034 p
= (char *)start
+ sizeof(struct smbios_entry_point
);
2036 #define add_struct(fn) { \
2039 if ((q - p) > max_struct_size) \
2040 max_struct_size = q - p; \
2044 add_struct(smbios_type_0_init(p
));
2045 add_struct(smbios_type_1_init(p
));
2046 add_struct(smbios_type_3_init(p
));
2047 for (cpu_num
= 1; cpu_num
<= smp_cpus
; cpu_num
++)
2048 add_struct(smbios_type_4_init(p
, cpu_num
));
2049 add_struct(smbios_type_16_init(p
, memsize
));
2050 add_struct(smbios_type_17_init(p
, memsize
));
2051 add_struct(smbios_type_19_init(p
, memsize
));
2052 add_struct(smbios_type_20_init(p
, memsize
));
2053 add_struct(smbios_type_32_init(p
));
2054 add_struct(smbios_type_127_init(p
));
2058 smbios_entry_point_init(
2059 start
, max_struct_size
,
2060 (p
- (char *)start
) - sizeof(struct smbios_entry_point
),
2061 (uint32_t)(start
+ sizeof(struct smbios_entry_point
)),
2064 #ifdef BX_USE_EBDA_TABLES
2065 ebda_cur_addr
+= (p
- (char *)start
);
2067 bios_table_cur_addr
+= (p
- (char *)start
);
2070 BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start
);
2073 void rombios32_init(void)
2075 BX_INFO("Starting rombios32\n");
2089 if (bios_table_cur_addr
!= 0) {
2098 bios_lock_shadow_ram();
2100 BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr
);
2101 if (bios_table_cur_addr
> bios_table_end_addr
)
2102 BX_PANIC("bios_table_end_addr overflow!\n");