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 uint8_t bios_uuid
[16];
420 #ifdef BX_USE_EBDA_TABLES
421 unsigned long ebda_cur_addr
;
424 uint32_t pm_io_base
, smb_io_base
;
426 unsigned long bios_table_cur_addr
;
427 unsigned long bios_table_end_addr
;
429 void init_smp_msrs(void)
431 *(uint32_t *)SMP_MSR_ADDR
= 0;
434 void wrmsr_smp(uint32_t index
, uint64_t val
)
436 static struct { uint32_t ecx
, eax
, edx
; } *p
= (void *)SMP_MSR_ADDR
;
446 void uuid_probe(void)
449 uint32_t eax
, ebx
, ecx
, edx
;
451 // check if backdoor port exists
452 asm volatile ("outl %%eax, %%dx"
453 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
454 : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
455 if (ebx
== 0x564d5868) {
456 uint32_t *uuid_ptr
= (uint32_t *)bios_uuid
;
458 asm volatile ("outl %%eax, %%dx"
459 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
460 : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
469 memset(bios_uuid
, 0, 16);
475 uint32_t eax
, ebx
, ecx
, edx
;
476 cpuid(1, eax
, ebx
, ecx
, edx
);
477 cpuid_signature
= eax
;
478 cpuid_features
= edx
;
479 cpuid_ext_features
= ecx
;
482 static int cmos_readb(int addr
)
488 void setup_mtrr(void)
490 int i
, vcnt
, fix
, wc
;
496 uint64_t vbase
, vmask
;
498 mtrr_cap
= rdmsr(MSR_MTRRcap
);
499 vcnt
= mtrr_cap
& 0xff;
500 fix
= mtrr_cap
& 0x100;
501 wc
= mtrr_cap
& 0x400;
505 for (i
= 0; i
< 8; ++i
)
506 if (ram_size
>= 65536 * (i
+ 1))
508 wrmsr_smp(MSR_MTRRfix64K_00000
, u
.val
);
510 for (i
= 0; i
< 8; ++i
)
511 if (ram_size
>= 65536 * 8 + 16384 * (i
+ 1))
513 wrmsr_smp(MSR_MTRRfix16K_80000
, u
.val
);
514 wrmsr_smp(MSR_MTRRfix16K_A0000
, 0);
515 wrmsr_smp(MSR_MTRRfix4K_C0000
, 0);
516 wrmsr_smp(MSR_MTRRfix4K_C8000
, 0);
517 wrmsr_smp(MSR_MTRRfix4K_D0000
, 0);
518 wrmsr_smp(MSR_MTRRfix4K_D8000
, 0);
519 wrmsr_smp(MSR_MTRRfix4K_E0000
, 0);
520 wrmsr_smp(MSR_MTRRfix4K_E8000
, 0);
521 wrmsr_smp(MSR_MTRRfix4K_F0000
, 0);
522 wrmsr_smp(MSR_MTRRfix4K_F8000
, 0);
524 --vcnt
; /* leave one mtrr for VRAM */
525 for (i
= 0; i
< vcnt
&& vbase
< ram_size
; ++i
) {
526 vmask
= (1ull << 40) - 1;
527 while (vbase
+ vmask
+ 1 > ram_size
)
529 wrmsr_smp(MTRRphysBase_MSR(i
), vbase
| 6);
530 wrmsr_smp(MTRRphysMask_MSR(i
), (~vmask
& 0xfffffff000ull
) | 0x800);
533 wrmsr_smp(MSR_MTRRdefType
, 0xc00);
538 if (cmos_readb(0x34) | cmos_readb(0x35))
539 ram_size
= (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
542 ram_size
= (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
543 #ifdef BX_USE_EBDA_TABLES
544 ebda_cur_addr
= ((*(uint16_t *)(0x40e)) << 4) + 0x380;
546 BX_INFO("ram_size=0x%08lx\n", ram_size
);
550 /****************************************************/
553 extern uint8_t smp_ap_boot_code_start
;
554 extern uint8_t smp_ap_boot_code_end
;
556 /* find the number of CPUs by launching a SIPI to them */
559 uint32_t val
, sipi_vector
;
562 if (cpuid_features
& CPUID_APIC
) {
564 /* enable local APIC */
565 val
= readl(APIC_BASE
+ APIC_SVR
);
567 writel(APIC_BASE
+ APIC_SVR
, val
);
569 writew((void *)CPU_COUNT_ADDR
, 1);
570 /* copy AP boot code */
571 memcpy((void *)AP_BOOT_ADDR
, &smp_ap_boot_code_start
,
572 &smp_ap_boot_code_end
- &smp_ap_boot_code_start
);
575 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4500);
576 sipi_vector
= AP_BOOT_ADDR
>> 12;
577 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4600 | sipi_vector
);
579 "xor %%eax, %%eax \n\t"
580 "xor %%edx, %%edx \n\t"
581 "mov $0x10, %%ecx \n\t"
583 : : : "eax", "ecx", "edx");
588 while (cmos_readb(0x5f) + 1 != readw((void *)CPU_COUNT_ADDR
))
592 smp_cpus
= readw((void *)CPU_COUNT_ADDR
);
594 BX_INFO("Found %d cpu(s)\n", smp_cpus
);
597 /****************************************************/
600 #define PCI_ADDRESS_SPACE_MEM 0x00
601 #define PCI_ADDRESS_SPACE_IO 0x01
602 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
604 #define PCI_ROM_SLOT 6
605 #define PCI_NUM_REGIONS 7
607 #define PCI_DEVICES_MAX 64
609 #define PCI_VENDOR_ID 0x00 /* 16 bits */
610 #define PCI_DEVICE_ID 0x02 /* 16 bits */
611 #define PCI_COMMAND 0x04 /* 16 bits */
612 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
613 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
614 #define PCI_CLASS_DEVICE 0x0a /* Device class */
615 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
616 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
617 #define PCI_MIN_GNT 0x3e /* 8 bits */
618 #define PCI_MAX_LAT 0x3f /* 8 bits */
620 typedef struct PCIDevice
{
625 static uint32_t pci_bios_io_addr
;
626 static uint32_t pci_bios_mem_addr
;
627 static uint32_t pci_bios_bigmem_addr
;
628 /* host irqs corresponding to PCI irqs A-D */
629 static uint8_t pci_irqs
[4] = { 10, 10, 11, 11 };
630 static PCIDevice i440_pcidev
;
632 static void pci_config_writel(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
634 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
638 static void pci_config_writew(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
640 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
641 outw(0xcfc + (addr
& 2), val
);
644 static void pci_config_writeb(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
646 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
647 outb(0xcfc + (addr
& 3), val
);
650 static uint32_t pci_config_readl(PCIDevice
*d
, uint32_t addr
)
652 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
656 static uint32_t pci_config_readw(PCIDevice
*d
, uint32_t addr
)
658 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
659 return inw(0xcfc + (addr
& 2));
662 static uint32_t pci_config_readb(PCIDevice
*d
, uint32_t addr
)
664 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
665 return inb(0xcfc + (addr
& 3));
668 static void pci_set_io_region_addr(PCIDevice
*d
, int region_num
, uint32_t addr
)
671 uint32_t ofs
, old_addr
;
673 if ( region_num
== PCI_ROM_SLOT
) {
676 ofs
= 0x10 + region_num
* 4;
679 old_addr
= pci_config_readl(d
, ofs
);
681 pci_config_writel(d
, ofs
, addr
);
682 BX_INFO("region %d: 0x%08x\n", region_num
, addr
);
684 /* enable memory mappings */
685 cmd
= pci_config_readw(d
, PCI_COMMAND
);
686 if ( region_num
== PCI_ROM_SLOT
)
688 else if (old_addr
& PCI_ADDRESS_SPACE_IO
)
692 pci_config_writew(d
, PCI_COMMAND
, cmd
);
695 /* return the global irq number corresponding to a given device irq
696 pin. We could also use the bus number to have a more precise
698 static int pci_slot_get_pirq(PCIDevice
*pci_dev
, int irq_num
)
701 slot_addend
= (pci_dev
->devfn
>> 3) - 1;
702 return (irq_num
+ slot_addend
) & 3;
705 static int find_bios_table_area(void)
708 for(addr
= 0xf0000; addr
< 0x100000; addr
+= 16) {
709 if (*(uint32_t *)addr
== 0xaafb4442) {
710 bios_table_cur_addr
= addr
+ 8;
711 bios_table_end_addr
= bios_table_cur_addr
+ *(uint32_t *)(addr
+ 4);
712 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
713 bios_table_cur_addr
, bios_table_end_addr
);
720 static void bios_shadow_init(PCIDevice
*d
)
724 if (find_bios_table_area() < 0)
727 /* remap the BIOS to shadow RAM an keep it read/write while we
728 are writing tables */
729 v
= pci_config_readb(d
, 0x59);
731 pci_config_writeb(d
, 0x59, v
);
732 memcpy((void *)BIOS_TMP_STORAGE
, (void *)0x000f0000, 0x10000);
734 pci_config_writeb(d
, 0x59, v
);
735 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE
, 0x10000);
740 static void bios_lock_shadow_ram(void)
742 PCIDevice
*d
= &i440_pcidev
;
746 v
= pci_config_readb(d
, 0x59);
747 v
= (v
& 0x0f) | (0x10);
748 pci_config_writeb(d
, 0x59, v
);
751 static void pci_bios_init_bridges(PCIDevice
*d
)
753 uint16_t vendor_id
, device_id
;
755 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
756 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
758 if (vendor_id
== 0x8086 && device_id
== 0x7000) {
766 for(i
= 0; i
< 4; i
++) {
768 /* set to trigger level */
769 elcr
[irq
>> 3] |= (1 << (irq
& 7));
770 /* activate irq remapping in PIIX */
771 pci_config_writeb(d
, 0x60 + i
, irq
);
773 outb(0x4d0, elcr
[0]);
774 outb(0x4d1, elcr
[1]);
775 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
777 } else if (vendor_id
== 0x8086 && device_id
== 0x1237) {
778 /* i440 PCI bridge */
783 extern uint8_t smm_relocation_start
, smm_relocation_end
;
784 extern uint8_t smm_code_start
, smm_code_end
;
787 static void smm_init(PCIDevice
*d
)
791 /* check if SMM init is already done */
792 value
= pci_config_readl(d
, 0x58);
793 if ((value
& (1 << 25)) == 0) {
795 /* copy the SMM relocation code */
796 memcpy((void *)0x38000, &smm_relocation_start
,
797 &smm_relocation_end
- &smm_relocation_start
);
799 /* enable SMI generation when writing to the APMC register */
800 pci_config_writel(d
, 0x58, value
| (1 << 25));
802 /* init APM status port */
805 /* raise an SMI interrupt */
808 /* wait until SMM code executed */
809 while (inb(0xb3) != 0x00);
811 /* enable the SMM memory window */
812 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x48);
814 /* copy the SMM code */
815 memcpy((void *)0xa8000, &smm_code_start
,
816 &smm_code_end
- &smm_code_start
);
819 /* close the SMM memory window and enable normal SMM */
820 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x08);
825 static void pci_bios_init_device(PCIDevice
*d
)
829 int i
, pin
, pic_irq
, vendor_id
, device_id
;
831 class = pci_config_readw(d
, PCI_CLASS_DEVICE
);
832 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
833 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
834 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
835 d
->bus
, d
->devfn
, vendor_id
, device_id
);
838 if (vendor_id
== 0x8086 && device_id
== 0x7010) {
840 pci_config_writew(d
, 0x40, 0x8000); // enable IDE0
841 pci_config_writew(d
, 0x42, 0x8000); // enable IDE1
844 /* IDE: we map it as in ISA mode */
845 pci_set_io_region_addr(d
, 0, 0x1f0);
846 pci_set_io_region_addr(d
, 1, 0x3f4);
847 pci_set_io_region_addr(d
, 2, 0x170);
848 pci_set_io_region_addr(d
, 3, 0x374);
852 if (vendor_id
!= 0x1234)
854 /* VGA: map frame buffer to default Bochs VBE address */
855 pci_set_io_region_addr(d
, 0, 0xE0000000);
859 if (vendor_id
== 0x1014) {
861 if (device_id
== 0x0046 || device_id
== 0xFFFF) {
863 pci_set_io_region_addr(d
, 0, 0x80800000 + 0x00040000);
868 if (vendor_id
== 0x0106b &&
869 (device_id
== 0x0017 || device_id
== 0x0022)) {
871 pci_set_io_region_addr(d
, 0, 0x80800000);
876 /* default memory mappings */
877 for(i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
881 if (i
== PCI_ROM_SLOT
)
885 pci_config_writel(d
, ofs
, 0xffffffff);
886 val
= pci_config_readl(d
, ofs
);
888 size
= (~(val
& ~0xf)) + 1;
889 if (val
& PCI_ADDRESS_SPACE_IO
)
890 paddr
= &pci_bios_io_addr
;
891 else if (size
>= 0x04000000)
892 paddr
= &pci_bios_bigmem_addr
;
894 paddr
= &pci_bios_mem_addr
;
895 *paddr
= (*paddr
+ size
- 1) & ~(size
- 1);
896 pci_set_io_region_addr(d
, i
, *paddr
);
903 /* map the interrupt */
904 pin
= pci_config_readb(d
, PCI_INTERRUPT_PIN
);
906 pin
= pci_slot_get_pirq(d
, pin
- 1);
907 pic_irq
= pci_irqs
[pin
];
908 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, pic_irq
);
911 if (vendor_id
== 0x8086 && device_id
== 0x7113) {
912 /* PIIX4 Power Management device (for ACPI) */
914 // acpi sci is hardwired to 9
915 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, 9);
917 pm_io_base
= PM_IO_BASE
;
918 pci_config_writel(d
, 0x40, pm_io_base
| 1);
919 pci_config_writeb(d
, 0x80, 0x01); /* enable PM io space */
920 smb_io_base
= SMB_IO_BASE
;
921 pci_config_writel(d
, 0x90, smb_io_base
| 1);
922 pci_config_writeb(d
, 0xd2, 0x09); /* enable SMBus io space */
923 pm_sci_int
= pci_config_readb(d
, PCI_INTERRUPT_LINE
);
931 void pci_for_each_device(void (*init_func
)(PCIDevice
*d
))
933 PCIDevice d1
, *d
= &d1
;
935 uint16_t vendor_id
, device_id
;
937 for(bus
= 0; bus
< 1; bus
++) {
938 for(devfn
= 0; devfn
< 256; devfn
++) {
941 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
942 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
943 if (vendor_id
!= 0xffff || device_id
!= 0xffff) {
950 void pci_bios_init(void)
952 pci_bios_io_addr
= 0xc000;
953 pci_bios_mem_addr
= 0xf0000000;
954 pci_bios_bigmem_addr
= ram_size
;
955 if (pci_bios_bigmem_addr
< 0x90000000)
956 pci_bios_bigmem_addr
= 0x90000000;
958 pci_for_each_device(pci_bios_init_bridges
);
960 pci_for_each_device(pci_bios_init_device
);
963 /****************************************************/
964 /* Multi Processor table init */
966 static void putb(uint8_t **pp
, int val
)
974 static void putstr(uint8_t **pp
, const char *str
)
983 static void putle16(uint8_t **pp
, int val
)
992 static void putle32(uint8_t **pp
, int val
)
1003 static int mpf_checksum(const uint8_t *data
, int len
)
1007 for(i
= 0; i
< len
; i
++)
1012 static unsigned long align(unsigned long addr
, unsigned long v
)
1014 return (addr
+ v
- 1) & ~(v
- 1);
1017 static void mptable_init(void)
1019 uint8_t *mp_config_table
, *q
, *float_pointer_struct
;
1020 int ioapic_id
, i
, len
;
1021 int mp_config_table_size
;
1023 #ifdef BX_USE_EBDA_TABLES
1024 mp_config_table
= (uint8_t *)(ram_size
- ACPI_DATA_SIZE
- MPTABLE_MAX_SIZE
);
1026 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1027 mp_config_table
= (uint8_t *)bios_table_cur_addr
;
1029 q
= mp_config_table
;
1030 putstr(&q
, "PCMP"); /* "PCMP signature */
1031 putle16(&q
, 0); /* table length (patched later) */
1032 putb(&q
, 4); /* spec rev */
1033 putb(&q
, 0); /* checksum (patched later) */
1035 putstr(&q
, "QEMUCPU "); /* OEM id */
1037 putstr(&q
, "BOCHSCPU");
1039 putstr(&q
, "0.1 "); /* vendor id */
1040 putle32(&q
, 0); /* OEM table ptr */
1041 putle16(&q
, 0); /* OEM table size */
1042 putle16(&q
, MAX_CPUS
+ 18); /* entry count */
1043 putle32(&q
, 0xfee00000); /* local APIC addr */
1044 putle16(&q
, 0); /* ext table length */
1045 putb(&q
, 0); /* ext table checksum */
1046 putb(&q
, 0); /* reserved */
1048 for(i
= 0; i
< MAX_CPUS
; i
++) {
1049 putb(&q
, 0); /* entry type = processor */
1050 putb(&q
, i
); /* APIC id */
1051 putb(&q
, 0x11); /* local APIC version number */
1053 putb(&q
, 3); /* cpu flags: enabled, bootstrap cpu */
1054 else if ( i
< smp_cpus
)
1055 putb(&q
, 1); /* cpu flags: enabled */
1057 putb(&q
, 0); /* cpu flags: disabled */
1058 putb(&q
, 0); /* cpu signature */
1062 putle16(&q
, 0x201); /* feature flags */
1065 putle16(&q
, 0); /* reserved */
1072 putb(&q
, 1); /* entry type = bus */
1073 putb(&q
, 0); /* bus ID */
1077 ioapic_id
= smp_cpus
;
1078 putb(&q
, 2); /* entry type = I/O APIC */
1079 putb(&q
, ioapic_id
); /* apic ID */
1080 putb(&q
, 0x11); /* I/O APIC version number */
1081 putb(&q
, 1); /* enable */
1082 putle32(&q
, 0xfec00000); /* I/O APIC addr */
1085 for(i
= 0; i
< 16; i
++) {
1086 putb(&q
, 3); /* entry type = I/O interrupt */
1087 putb(&q
, 0); /* interrupt type = vectored interrupt */
1088 putb(&q
, 0); /* flags: po=0, el=0 */
1090 putb(&q
, 0); /* source bus ID = ISA */
1091 putb(&q
, i
); /* source bus IRQ */
1092 putb(&q
, ioapic_id
); /* dest I/O APIC ID */
1093 putb(&q
, i
); /* dest I/O APIC interrupt in */
1096 len
= q
- mp_config_table
;
1097 mp_config_table
[4] = len
;
1098 mp_config_table
[5] = len
>> 8;
1100 mp_config_table
[7] = -mpf_checksum(mp_config_table
, q
- mp_config_table
);
1102 mp_config_table_size
= q
- mp_config_table
;
1104 #ifndef BX_USE_EBDA_TABLES
1105 bios_table_cur_addr
+= mp_config_table_size
;
1108 /* floating pointer structure */
1109 #ifdef BX_USE_EBDA_TABLES
1110 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1111 float_pointer_struct
= (uint8_t *)ebda_cur_addr
;
1113 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1114 float_pointer_struct
= (uint8_t *)bios_table_cur_addr
;
1116 q
= float_pointer_struct
;
1118 /* pointer to MP config table */
1119 putle32(&q
, (unsigned long)mp_config_table
);
1121 putb(&q
, 1); /* length in 16 byte units */
1122 putb(&q
, 4); /* MP spec revision */
1123 putb(&q
, 0); /* checksum (patched later) */
1124 putb(&q
, 0); /* MP feature byte 1 */
1130 float_pointer_struct
[10] =
1131 -mpf_checksum(float_pointer_struct
, q
- float_pointer_struct
);
1132 #ifdef BX_USE_EBDA_TABLES
1133 ebda_cur_addr
+= (q
- float_pointer_struct
);
1135 bios_table_cur_addr
+= (q
- float_pointer_struct
);
1137 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
1138 (unsigned long)float_pointer_struct
,
1139 (unsigned long)mp_config_table
,
1140 mp_config_table_size
);
1143 /****************************************************/
1144 /* ACPI tables init */
1146 /* Table structure from Linux kernel (the ACPI tables are under the
1149 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
1150 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
1151 uint32_t length; /* Length of table, in bytes, including header */\
1152 uint8_t revision; /* ACPI Specification minor version # */\
1153 uint8_t checksum; /* To make sum of entire table == 0 */\
1154 uint8_t oem_id [6]; /* OEM identification */\
1155 uint8_t oem_table_id [8]; /* OEM table identification */\
1156 uint32_t oem_revision; /* OEM revision number */\
1157 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
1158 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1161 struct acpi_table_header
/* ACPI common table header */
1163 ACPI_TABLE_HEADER_DEF
1166 struct rsdp_descriptor
/* Root System Descriptor Pointer */
1168 uint8_t signature
[8]; /* ACPI signature, contains "RSD PTR " */
1169 uint8_t checksum
; /* To make sum of struct == 0 */
1170 uint8_t oem_id
[6]; /* OEM identification */
1171 uint8_t revision
; /* Must be 0 for 1.0, 2 for 2.0 */
1172 uint32_t rsdt_physical_address
; /* 32-bit physical address of RSDT */
1173 uint32_t length
; /* XSDT Length in bytes including hdr */
1174 uint64_t xsdt_physical_address
; /* 64-bit physical address of XSDT */
1175 uint8_t extended_checksum
; /* Checksum of entire table */
1176 uint8_t reserved
[3]; /* Reserved field must be 0 */
1180 * ACPI 1.0 Root System Description Table (RSDT)
1182 struct rsdt_descriptor_rev1
1184 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1185 uint32_t table_offset_entry
[2]; /* Array of pointers to other */
1190 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1192 struct facs_descriptor_rev1
1194 uint8_t signature
[4]; /* ACPI Signature */
1195 uint32_t length
; /* Length of structure, in bytes */
1196 uint32_t hardware_signature
; /* Hardware configuration signature */
1197 uint32_t firmware_waking_vector
; /* ACPI OS waking vector */
1198 uint32_t global_lock
; /* Global Lock */
1199 uint32_t S4bios_f
: 1; /* Indicates if S4BIOS support is present */
1200 uint32_t reserved1
: 31; /* Must be 0 */
1201 uint8_t resverved3
[40]; /* Reserved - must be zero */
1206 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1208 struct fadt_descriptor_rev1
1210 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1211 uint32_t firmware_ctrl
; /* Physical address of FACS */
1212 uint32_t dsdt
; /* Physical address of DSDT */
1213 uint8_t model
; /* System Interrupt Model */
1214 uint8_t reserved1
; /* Reserved */
1215 uint16_t sci_int
; /* System vector of SCI interrupt */
1216 uint32_t smi_cmd
; /* Port address of SMI command port */
1217 uint8_t acpi_enable
; /* Value to write to smi_cmd to enable ACPI */
1218 uint8_t acpi_disable
; /* Value to write to smi_cmd to disable ACPI */
1219 uint8_t S4bios_req
; /* Value to write to SMI CMD to enter S4BIOS state */
1220 uint8_t reserved2
; /* Reserved - must be zero */
1221 uint32_t pm1a_evt_blk
; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1222 uint32_t pm1b_evt_blk
; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1223 uint32_t pm1a_cnt_blk
; /* Port address of Power Mgt 1a Control Reg Blk */
1224 uint32_t pm1b_cnt_blk
; /* Port address of Power Mgt 1b Control Reg Blk */
1225 uint32_t pm2_cnt_blk
; /* Port address of Power Mgt 2 Control Reg Blk */
1226 uint32_t pm_tmr_blk
; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1227 uint32_t gpe0_blk
; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1228 uint32_t gpe1_blk
; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1229 uint8_t pm1_evt_len
; /* Byte length of ports at pm1_x_evt_blk */
1230 uint8_t pm1_cnt_len
; /* Byte length of ports at pm1_x_cnt_blk */
1231 uint8_t pm2_cnt_len
; /* Byte Length of ports at pm2_cnt_blk */
1232 uint8_t pm_tmr_len
; /* Byte Length of ports at pm_tm_blk */
1233 uint8_t gpe0_blk_len
; /* Byte Length of ports at gpe0_blk */
1234 uint8_t gpe1_blk_len
; /* Byte Length of ports at gpe1_blk */
1235 uint8_t gpe1_base
; /* Offset in gpe model where gpe1 events start */
1236 uint8_t reserved3
; /* Reserved */
1237 uint16_t plvl2_lat
; /* Worst case HW latency to enter/exit C2 state */
1238 uint16_t plvl3_lat
; /* Worst case HW latency to enter/exit C3 state */
1239 uint16_t flush_size
; /* Size of area read to flush caches */
1240 uint16_t flush_stride
; /* Stride used in flushing caches */
1241 uint8_t duty_offset
; /* Bit location of duty cycle field in p_cnt reg */
1242 uint8_t duty_width
; /* Bit width of duty cycle field in p_cnt reg */
1243 uint8_t day_alrm
; /* Index to day-of-month alarm in RTC CMOS RAM */
1244 uint8_t mon_alrm
; /* Index to month-of-year alarm in RTC CMOS RAM */
1245 uint8_t century
; /* Index to century in RTC CMOS RAM */
1246 uint8_t reserved4
; /* Reserved */
1247 uint8_t reserved4a
; /* Reserved */
1248 uint8_t reserved4b
; /* Reserved */
1250 uint32_t wb_invd
: 1; /* The wbinvd instruction works properly */
1251 uint32_t wb_invd_flush
: 1; /* The wbinvd flushes but does not invalidate */
1252 uint32_t proc_c1
: 1; /* All processors support C1 state */
1253 uint32_t plvl2_up
: 1; /* C2 state works on MP system */
1254 uint32_t pwr_button
: 1; /* Power button is handled as a generic feature */
1255 uint32_t sleep_button
: 1; /* Sleep button is handled as a generic feature, or not present */
1256 uint32_t fixed_rTC
: 1; /* RTC wakeup stat not in fixed register space */
1257 uint32_t rtcs4
: 1; /* RTC wakeup stat not possible from S4 */
1258 uint32_t tmr_val_ext
: 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1259 uint32_t reserved5
: 23; /* Reserved - must be zero */
1266 * MADT values and structures
1269 /* Values for MADT PCATCompat */
1272 #define MULTIPLE_APIC 1
1277 struct multiple_apic_table
1279 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1280 uint32_t local_apic_address
; /* Physical address of local APIC */
1282 uint32_t PCATcompat
: 1; /* A one indicates system also has dual 8259s */
1283 uint32_t reserved1
: 31;
1290 /* Values for Type in APIC_HEADER_DEF */
1292 #define APIC_PROCESSOR 0
1294 #define APIC_XRUPT_OVERRIDE 2
1296 #define APIC_LOCAL_NMI 4
1297 #define APIC_ADDRESS_OVERRIDE 5
1298 #define APIC_IO_SAPIC 6
1299 #define APIC_LOCAL_SAPIC 7
1300 #define APIC_XRUPT_SOURCE 8
1301 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1304 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1306 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1310 /* Sub-structures for MADT */
1312 struct madt_processor_apic
1315 uint8_t processor_id
; /* ACPI processor id */
1316 uint8_t local_apic_id
; /* Processor's local APIC id */
1318 uint32_t processor_enabled
: 1; /* Processor is usable if set */
1319 uint32_t reserved2
: 31; /* Reserved, must be zero */
1328 uint8_t io_apic_id
; /* I/O APIC ID */
1329 uint8_t reserved
; /* Reserved - must be zero */
1330 uint32_t address
; /* APIC physical address */
1331 uint32_t interrupt
; /* Global system interrupt where INTI
1335 struct madt_intsrcovr
{
1341 } __attribute__((packed
));
1343 #include "acpi-dsdt.hex"
1345 static inline uint16_t cpu_to_le16(uint16_t x
)
1350 static inline uint32_t cpu_to_le32(uint32_t x
)
1355 static int acpi_checksum(const uint8_t *data
, int len
)
1359 for(i
= 0; i
< len
; i
++)
1361 return (-sum
) & 0xff;
1364 static void acpi_build_table_header(struct acpi_table_header
*h
,
1365 char *sig
, int len
, uint8_t rev
)
1367 memcpy(h
->signature
, sig
, 4);
1368 h
->length
= cpu_to_le32(len
);
1371 memcpy(h
->oem_id
, "QEMU ", 6);
1372 memcpy(h
->oem_table_id
, "QEMU", 4);
1374 memcpy(h
->oem_id
, "BOCHS ", 6);
1375 memcpy(h
->oem_table_id
, "BXPC", 4);
1377 memcpy(h
->oem_table_id
+ 4, sig
, 4);
1378 h
->oem_revision
= cpu_to_le32(1);
1380 memcpy(h
->asl_compiler_id
, "QEMU", 4);
1382 memcpy(h
->asl_compiler_id
, "BXPC", 4);
1384 h
->asl_compiler_revision
= cpu_to_le32(1);
1385 h
->checksum
= acpi_checksum((void *)h
, len
);
1388 /* base_addr must be a multiple of 4KB */
1389 void acpi_bios_init(void)
1391 struct rsdp_descriptor
*rsdp
;
1392 struct rsdt_descriptor_rev1
*rsdt
;
1393 struct fadt_descriptor_rev1
*fadt
;
1394 struct facs_descriptor_rev1
*facs
;
1395 struct multiple_apic_table
*madt
;
1397 uint32_t base_addr
, rsdt_addr
, fadt_addr
, addr
, facs_addr
, dsdt_addr
;
1398 uint32_t acpi_tables_size
, madt_addr
, madt_size
;
1401 /* reserve memory space for tables */
1402 #ifdef BX_USE_EBDA_TABLES
1403 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1404 rsdp
= (void *)(ebda_cur_addr
);
1405 ebda_cur_addr
+= sizeof(*rsdp
);
1407 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1408 rsdp
= (void *)(bios_table_cur_addr
);
1409 bios_table_cur_addr
+= sizeof(*rsdp
);
1412 addr
= base_addr
= ram_size
- ACPI_DATA_SIZE
;
1414 rsdt
= (void *)(addr
);
1415 addr
+= sizeof(*rsdt
);
1418 fadt
= (void *)(addr
);
1419 addr
+= sizeof(*fadt
);
1421 /* XXX: FACS should be in RAM */
1422 addr
= (addr
+ 63) & ~63; /* 64 byte alignment for FACS */
1424 facs
= (void *)(addr
);
1425 addr
+= sizeof(*facs
);
1428 dsdt
= (void *)(addr
);
1429 addr
+= sizeof(AmlCode
);
1431 addr
= (addr
+ 7) & ~7;
1433 madt_size
= sizeof(*madt
) +
1434 sizeof(struct madt_processor_apic
) * MAX_CPUS
+
1435 sizeof(struct madt_io_apic
);
1436 madt
= (void *)(addr
);
1439 acpi_tables_size
= addr
- base_addr
;
1441 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1442 (unsigned long)rsdp
,
1443 (unsigned long)rsdt
, acpi_tables_size
);
1446 memset(rsdp
, 0, sizeof(*rsdp
));
1447 memcpy(rsdp
->signature
, "RSD PTR ", 8);
1449 memcpy(rsdp
->oem_id
, "QEMU ", 6);
1451 memcpy(rsdp
->oem_id
, "BOCHS ", 6);
1453 rsdp
->rsdt_physical_address
= cpu_to_le32(rsdt_addr
);
1454 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
1457 memset(rsdt
, 0, sizeof(*rsdt
));
1458 rsdt
->table_offset_entry
[0] = cpu_to_le32(fadt_addr
);
1459 rsdt
->table_offset_entry
[1] = cpu_to_le32(madt_addr
);
1460 acpi_build_table_header((struct acpi_table_header
*)rsdt
,
1461 "RSDT", sizeof(*rsdt
), 1);
1464 memset(fadt
, 0, sizeof(*fadt
));
1465 fadt
->firmware_ctrl
= cpu_to_le32(facs_addr
);
1466 fadt
->dsdt
= cpu_to_le32(dsdt_addr
);
1468 fadt
->reserved1
= 0;
1469 fadt
->sci_int
= cpu_to_le16(pm_sci_int
);
1470 fadt
->smi_cmd
= cpu_to_le32(SMI_CMD_IO_ADDR
);
1471 fadt
->acpi_enable
= 0xf1;
1472 fadt
->acpi_disable
= 0xf0;
1473 fadt
->pm1a_evt_blk
= cpu_to_le32(pm_io_base
);
1474 fadt
->pm1a_cnt_blk
= cpu_to_le32(pm_io_base
+ 0x04);
1475 fadt
->pm_tmr_blk
= cpu_to_le32(pm_io_base
+ 0x08);
1476 fadt
->pm1_evt_len
= 4;
1477 fadt
->pm1_cnt_len
= 2;
1478 fadt
->pm_tmr_len
= 4;
1479 fadt
->plvl2_lat
= cpu_to_le16(0x0fff); // C2 state not supported
1480 fadt
->plvl3_lat
= cpu_to_le16(0x0fff); // C3 state not supported
1481 fadt
->gpe0_blk
= cpu_to_le32(0xafe0);
1482 fadt
->gpe0_blk_len
= 4;
1483 /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
1484 fadt
->flags
= cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
1485 acpi_build_table_header((struct acpi_table_header
*)fadt
, "FACP",
1489 memset(facs
, 0, sizeof(*facs
));
1490 memcpy(facs
->signature
, "FACS", 4);
1491 facs
->length
= cpu_to_le32(sizeof(*facs
));
1494 memcpy(dsdt
, AmlCode
, sizeof(AmlCode
));
1498 struct madt_processor_apic
*apic
;
1499 struct madt_io_apic
*io_apic
;
1500 struct madt_intsrcovr
*intsrcovr
;
1502 memset(madt
, 0, madt_size
);
1503 madt
->local_apic_address
= cpu_to_le32(0xfee00000);
1504 madt
->flags
= cpu_to_le32(1);
1505 apic
= (void *)(madt
+ 1);
1506 for(i
=0;i
<MAX_CPUS
;i
++) {
1507 apic
->type
= APIC_PROCESSOR
;
1508 apic
->length
= sizeof(*apic
);
1509 apic
->processor_id
= i
;
1510 apic
->local_apic_id
= i
;
1512 apic
->flags
= cpu_to_le32(1);
1517 io_apic
= (void *)apic
;
1518 io_apic
->type
= APIC_IO
;
1519 io_apic
->length
= sizeof(*io_apic
);
1520 io_apic
->io_apic_id
= smp_cpus
;
1521 io_apic
->address
= cpu_to_le32(0xfec00000);
1522 io_apic
->interrupt
= cpu_to_le32(0);
1524 intsrcovr
= (struct madt_intsrcovr
*)(io_apic
+ 1);
1525 for ( i
= 0; i
< 16; i
++ ) {
1526 if ( PCI_ISA_IRQ_MASK
& (1U << i
) ) {
1527 memset(intsrcovr
, 0, sizeof(*intsrcovr
));
1528 intsrcovr
->type
= APIC_XRUPT_OVERRIDE
;
1529 intsrcovr
->length
= sizeof(*intsrcovr
);
1530 intsrcovr
->source
= i
;
1532 intsrcovr
->flags
= 0xd; /* active high, level triggered */
1534 /* No need for a INT source override structure. */
1538 madt_size
+= sizeof(struct madt_intsrcovr
);
1540 acpi_build_table_header((struct acpi_table_header
*)madt
,
1541 "APIC", madt_size
, 1);
1545 /* SMBIOS entry point -- must be written to a 16-bit aligned address
1546 between 0xf0000 and 0xfffff.
1548 struct smbios_entry_point
{
1549 char anchor_string
[4];
1552 uint8_t smbios_major_version
;
1553 uint8_t smbios_minor_version
;
1554 uint16_t max_structure_size
;
1555 uint8_t entry_point_revision
;
1556 uint8_t formatted_area
[5];
1557 char intermediate_anchor_string
[5];
1558 uint8_t intermediate_checksum
;
1559 uint16_t structure_table_length
;
1560 uint32_t structure_table_address
;
1561 uint16_t number_of_structures
;
1562 uint8_t smbios_bcd_revision
;
1563 } __attribute__((__packed__
));
1565 /* This goes at the beginning of every SMBIOS structure. */
1566 struct smbios_structure_header
{
1570 } __attribute__((__packed__
));
1572 /* SMBIOS type 0 - BIOS Information */
1573 struct smbios_type_0
{
1574 struct smbios_structure_header header
;
1576 uint8_t bios_version_str
;
1577 uint16_t bios_starting_address_segment
;
1578 uint8_t bios_release_date_str
;
1579 uint8_t bios_rom_size
;
1580 uint8_t bios_characteristics
[8];
1581 uint8_t bios_characteristics_extension_bytes
[2];
1582 uint8_t system_bios_major_release
;
1583 uint8_t system_bios_minor_release
;
1584 uint8_t embedded_controller_major_release
;
1585 uint8_t embedded_controller_minor_release
;
1586 } __attribute__((__packed__
));
1588 /* SMBIOS type 1 - System Information */
1589 struct smbios_type_1
{
1590 struct smbios_structure_header header
;
1591 uint8_t manufacturer_str
;
1592 uint8_t product_name_str
;
1593 uint8_t version_str
;
1594 uint8_t serial_number_str
;
1596 uint8_t wake_up_type
;
1597 uint8_t sku_number_str
;
1599 } __attribute__((__packed__
));
1601 /* SMBIOS type 3 - System Enclosure (v2.3) */
1602 struct smbios_type_3
{
1603 struct smbios_structure_header header
;
1604 uint8_t manufacturer_str
;
1606 uint8_t version_str
;
1607 uint8_t serial_number_str
;
1608 uint8_t asset_tag_number_str
;
1609 uint8_t boot_up_state
;
1610 uint8_t power_supply_state
;
1611 uint8_t thermal_state
;
1612 uint8_t security_status
;
1613 uint32_t oem_defined
;
1615 uint8_t number_of_power_cords
;
1616 uint8_t contained_element_count
;
1617 // contained elements follow
1618 } __attribute__((__packed__
));
1620 /* SMBIOS type 4 - Processor Information (v2.0) */
1621 struct smbios_type_4
{
1622 struct smbios_structure_header header
;
1623 uint8_t socket_designation_str
;
1624 uint8_t processor_type
;
1625 uint8_t processor_family
;
1626 uint8_t processor_manufacturer_str
;
1627 uint32_t processor_id
[2];
1628 uint8_t processor_version_str
;
1630 uint16_t external_clock
;
1632 uint16_t current_speed
;
1634 uint8_t processor_upgrade
;
1635 } __attribute__((__packed__
));
1637 /* SMBIOS type 16 - Physical Memory Array
1638 * Associated with one type 17 (Memory Device).
1640 struct smbios_type_16
{
1641 struct smbios_structure_header header
;
1644 uint8_t error_correction
;
1645 uint32_t maximum_capacity
;
1646 uint16_t memory_error_information_handle
;
1647 uint16_t number_of_memory_devices
;
1648 } __attribute__((__packed__
));
1650 /* SMBIOS type 17 - Memory Device
1651 * Associated with one type 19
1653 struct smbios_type_17
{
1654 struct smbios_structure_header header
;
1655 uint16_t physical_memory_array_handle
;
1656 uint16_t memory_error_information_handle
;
1657 uint16_t total_width
;
1658 uint16_t data_width
;
1660 uint8_t form_factor
;
1662 uint8_t device_locator_str
;
1663 uint8_t bank_locator_str
;
1664 uint8_t memory_type
;
1665 uint16_t type_detail
;
1666 } __attribute__((__packed__
));
1668 /* SMBIOS type 19 - Memory Array Mapped Address */
1669 struct smbios_type_19
{
1670 struct smbios_structure_header header
;
1671 uint32_t starting_address
;
1672 uint32_t ending_address
;
1673 uint16_t memory_array_handle
;
1674 uint8_t partition_width
;
1675 } __attribute__((__packed__
));
1677 /* SMBIOS type 20 - Memory Device Mapped Address */
1678 struct smbios_type_20
{
1679 struct smbios_structure_header header
;
1680 uint32_t starting_address
;
1681 uint32_t ending_address
;
1682 uint16_t memory_device_handle
;
1683 uint16_t memory_array_mapped_address_handle
;
1684 uint8_t partition_row_position
;
1685 uint8_t interleave_position
;
1686 uint8_t interleaved_data_depth
;
1687 } __attribute__((__packed__
));
1689 /* SMBIOS type 32 - System Boot Information */
1690 struct smbios_type_32
{
1691 struct smbios_structure_header header
;
1692 uint8_t reserved
[6];
1693 uint8_t boot_status
;
1694 } __attribute__((__packed__
));
1696 /* SMBIOS type 127 -- End-of-table */
1697 struct smbios_type_127
{
1698 struct smbios_structure_header header
;
1699 } __attribute__((__packed__
));
1702 smbios_entry_point_init(void *start
,
1703 uint16_t max_structure_size
,
1704 uint16_t structure_table_length
,
1705 uint32_t structure_table_address
,
1706 uint16_t number_of_structures
)
1710 struct smbios_entry_point
*ep
= (struct smbios_entry_point
*)start
;
1712 memcpy(ep
->anchor_string
, "_SM_", 4);
1714 ep
->smbios_major_version
= 2;
1715 ep
->smbios_minor_version
= 4;
1716 ep
->max_structure_size
= max_structure_size
;
1717 ep
->entry_point_revision
= 0;
1718 memset(ep
->formatted_area
, 0, 5);
1719 memcpy(ep
->intermediate_anchor_string
, "_DMI_", 5);
1721 ep
->structure_table_length
= structure_table_length
;
1722 ep
->structure_table_address
= structure_table_address
;
1723 ep
->number_of_structures
= number_of_structures
;
1724 ep
->smbios_bcd_revision
= 0x24;
1727 ep
->intermediate_checksum
= 0;
1730 for (i
= 0; i
< 0x10; i
++)
1731 sum
+= ((int8_t *)start
)[i
];
1732 ep
->checksum
= -sum
;
1735 for (i
= 0x10; i
< ep
->length
; i
++)
1736 sum
+= ((int8_t *)start
)[i
];
1737 ep
->intermediate_checksum
= -sum
;
1740 /* Type 0 -- BIOS Information */
1741 #define RELEASE_DATE_STR "01/01/2007"
1743 smbios_type_0_init(void *start
)
1745 struct smbios_type_0
*p
= (struct smbios_type_0
*)start
;
1748 p
->header
.length
= sizeof(struct smbios_type_0
);
1749 p
->header
.handle
= 0;
1752 p
->bios_version_str
= 1;
1753 p
->bios_starting_address_segment
= 0xe800;
1754 p
->bios_release_date_str
= 2;
1755 p
->bios_rom_size
= 0; /* FIXME */
1757 memset(p
->bios_characteristics
, 0, 7);
1758 p
->bios_characteristics
[7] = 0x08; /* BIOS characteristics not supported */
1759 p
->bios_characteristics_extension_bytes
[0] = 0;
1760 p
->bios_characteristics_extension_bytes
[1] = 0;
1762 p
->system_bios_major_release
= 1;
1763 p
->system_bios_minor_release
= 0;
1764 p
->embedded_controller_major_release
= 0xff;
1765 p
->embedded_controller_minor_release
= 0xff;
1767 start
+= sizeof(struct smbios_type_0
);
1768 memcpy((char *)start
, BX_APPNAME
, sizeof(BX_APPNAME
));
1769 start
+= sizeof(BX_APPNAME
);
1770 memcpy((char *)start
, RELEASE_DATE_STR
, sizeof(RELEASE_DATE_STR
));
1771 start
+= sizeof(RELEASE_DATE_STR
);
1772 *((uint8_t *)start
) = 0;
1777 /* Type 1 -- System Information */
1779 smbios_type_1_init(void *start
)
1781 struct smbios_type_1
*p
= (struct smbios_type_1
*)start
;
1783 p
->header
.length
= sizeof(struct smbios_type_1
);
1784 p
->header
.handle
= 0x100;
1786 p
->manufacturer_str
= 0;
1787 p
->product_name_str
= 0;
1789 p
->serial_number_str
= 0;
1791 memcpy(p
->uuid
, bios_uuid
, 16);
1793 p
->wake_up_type
= 0x06; /* power switch */
1794 p
->sku_number_str
= 0;
1797 start
+= sizeof(struct smbios_type_1
);
1798 *((uint16_t *)start
) = 0;
1803 /* Type 3 -- System Enclosure */
1805 smbios_type_3_init(void *start
)
1807 struct smbios_type_3
*p
= (struct smbios_type_3
*)start
;
1810 p
->header
.length
= sizeof(struct smbios_type_3
);
1811 p
->header
.handle
= 0x300;
1813 p
->manufacturer_str
= 0;
1814 p
->type
= 0x01; /* other */
1816 p
->serial_number_str
= 0;
1817 p
->asset_tag_number_str
= 0;
1818 p
->boot_up_state
= 0x03; /* safe */
1819 p
->power_supply_state
= 0x03; /* safe */
1820 p
->thermal_state
= 0x03; /* safe */
1821 p
->security_status
= 0x02; /* unknown */
1824 p
->number_of_power_cords
= 0;
1825 p
->contained_element_count
= 0;
1827 start
+= sizeof(struct smbios_type_3
);
1828 *((uint16_t *)start
) = 0;
1833 /* Type 4 -- Processor Information */
1835 smbios_type_4_init(void *start
, unsigned int cpu_number
)
1837 struct smbios_type_4
*p
= (struct smbios_type_4
*)start
;
1840 p
->header
.length
= sizeof(struct smbios_type_4
);
1841 p
->header
.handle
= 0x400 + cpu_number
;
1843 p
->socket_designation_str
= 1;
1844 p
->processor_type
= 0x03; /* CPU */
1845 p
->processor_family
= 0x01; /* other */
1846 p
->processor_manufacturer_str
= 0;
1848 p
->processor_id
[0] = cpuid_signature
;
1849 p
->processor_id
[1] = cpuid_features
;
1851 p
->processor_version_str
= 0;
1853 p
->external_clock
= 0;
1855 p
->max_speed
= 0; /* unknown */
1856 p
->current_speed
= 0; /* unknown */
1858 p
->status
= 0x41; /* socket populated, CPU enabled */
1859 p
->processor_upgrade
= 0x01; /* other */
1861 start
+= sizeof(struct smbios_type_4
);
1863 memcpy((char *)start
, "CPU " "\0" "" "\0" "", 7);
1864 ((char *)start
)[4] = cpu_number
+ '0';
1869 /* Type 16 -- Physical Memory Array */
1871 smbios_type_16_init(void *start
, uint32_t memsize
)
1873 struct smbios_type_16
*p
= (struct smbios_type_16
*)start
;
1875 p
->header
.type
= 16;
1876 p
->header
.length
= sizeof(struct smbios_type_16
);
1877 p
->header
.handle
= 0x1000;
1879 p
->location
= 0x01; /* other */
1880 p
->use
= 0x03; /* system memory */
1881 p
->error_correction
= 0x01; /* other */
1882 p
->maximum_capacity
= memsize
* 1024;
1883 p
->memory_error_information_handle
= 0xfffe; /* none provided */
1884 p
->number_of_memory_devices
= 1;
1886 start
+= sizeof(struct smbios_type_16
);
1887 *((uint16_t *)start
) = 0;
1892 /* Type 17 -- Memory Device */
1894 smbios_type_17_init(void *start
, uint32_t memory_size_mb
)
1896 struct smbios_type_17
*p
= (struct smbios_type_17
*)start
;
1898 p
->header
.type
= 17;
1899 p
->header
.length
= sizeof(struct smbios_type_17
);
1900 p
->header
.handle
= 0x1100;
1902 p
->physical_memory_array_handle
= 0x1000;
1903 p
->total_width
= 64;
1905 /* truncate memory_size_mb to 16 bits and clear most significant
1906 bit [indicates size in MB] */
1907 p
->size
= (uint16_t) memory_size_mb
& 0x7fff;
1908 p
->form_factor
= 0x09; /* DIMM */
1910 p
->device_locator_str
= 1;
1911 p
->bank_locator_str
= 0;
1912 p
->memory_type
= 0x07; /* RAM */
1915 start
+= sizeof(struct smbios_type_17
);
1916 memcpy((char *)start
, "DIMM 1", 7);
1918 *((uint8_t *)start
) = 0;
1923 /* Type 19 -- Memory Array Mapped Address */
1925 smbios_type_19_init(void *start
, uint32_t memory_size_mb
)
1927 struct smbios_type_19
*p
= (struct smbios_type_19
*)start
;
1929 p
->header
.type
= 19;
1930 p
->header
.length
= sizeof(struct smbios_type_19
);
1931 p
->header
.handle
= 0x1300;
1933 p
->starting_address
= 0;
1934 p
->ending_address
= (memory_size_mb
-1) * 1024;
1935 p
->memory_array_handle
= 0x1000;
1936 p
->partition_width
= 1;
1938 start
+= sizeof(struct smbios_type_19
);
1939 *((uint16_t *)start
) = 0;
1944 /* Type 20 -- Memory Device Mapped Address */
1946 smbios_type_20_init(void *start
, uint32_t memory_size_mb
)
1948 struct smbios_type_20
*p
= (struct smbios_type_20
*)start
;
1950 p
->header
.type
= 20;
1951 p
->header
.length
= sizeof(struct smbios_type_20
);
1952 p
->header
.handle
= 0x1400;
1954 p
->starting_address
= 0;
1955 p
->ending_address
= (memory_size_mb
-1)*1024;
1956 p
->memory_device_handle
= 0x1100;
1957 p
->memory_array_mapped_address_handle
= 0x1300;
1958 p
->partition_row_position
= 1;
1959 p
->interleave_position
= 0;
1960 p
->interleaved_data_depth
= 0;
1962 start
+= sizeof(struct smbios_type_20
);
1964 *((uint16_t *)start
) = 0;
1968 /* Type 32 -- System Boot Information */
1970 smbios_type_32_init(void *start
)
1972 struct smbios_type_32
*p
= (struct smbios_type_32
*)start
;
1974 p
->header
.type
= 32;
1975 p
->header
.length
= sizeof(struct smbios_type_32
);
1976 p
->header
.handle
= 0x2000;
1977 memset(p
->reserved
, 0, 6);
1978 p
->boot_status
= 0; /* no errors detected */
1980 start
+= sizeof(struct smbios_type_32
);
1981 *((uint16_t *)start
) = 0;
1986 /* Type 127 -- End of Table */
1988 smbios_type_127_init(void *start
)
1990 struct smbios_type_127
*p
= (struct smbios_type_127
*)start
;
1992 p
->header
.type
= 127;
1993 p
->header
.length
= sizeof(struct smbios_type_127
);
1994 p
->header
.handle
= 0x7f00;
1996 start
+= sizeof(struct smbios_type_127
);
1997 *((uint16_t *)start
) = 0;
2002 void smbios_init(void)
2004 unsigned cpu_num
, nr_structs
= 0, max_struct_size
= 0;
2005 char *start
, *p
, *q
;
2006 int memsize
= ram_size
/ (1024 * 1024);
2008 #ifdef BX_USE_EBDA_TABLES
2009 ebda_cur_addr
= align(ebda_cur_addr
, 16);
2010 start
= (void *)(ebda_cur_addr
);
2012 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
2013 start
= (void *)(bios_table_cur_addr
);
2016 p
= (char *)start
+ sizeof(struct smbios_entry_point
);
2018 #define add_struct(fn) { \
2021 if ((q - p) > max_struct_size) \
2022 max_struct_size = q - p; \
2026 add_struct(smbios_type_0_init(p
));
2027 add_struct(smbios_type_1_init(p
));
2028 add_struct(smbios_type_3_init(p
));
2029 for (cpu_num
= 1; cpu_num
<= smp_cpus
; cpu_num
++)
2030 add_struct(smbios_type_4_init(p
, cpu_num
));
2031 add_struct(smbios_type_16_init(p
, memsize
));
2032 add_struct(smbios_type_17_init(p
, memsize
));
2033 add_struct(smbios_type_19_init(p
, memsize
));
2034 add_struct(smbios_type_20_init(p
, memsize
));
2035 add_struct(smbios_type_32_init(p
));
2036 add_struct(smbios_type_127_init(p
));
2040 smbios_entry_point_init(
2041 start
, max_struct_size
,
2042 (p
- (char *)start
) - sizeof(struct smbios_entry_point
),
2043 (uint32_t)(start
+ sizeof(struct smbios_entry_point
)),
2046 #ifdef BX_USE_EBDA_TABLES
2047 ebda_cur_addr
+= (p
- (char *)start
);
2049 bios_table_cur_addr
+= (p
- (char *)start
);
2052 BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start
);
2055 void rombios32_init(void)
2057 BX_INFO("Starting rombios32\n");
2071 if (bios_table_cur_addr
!= 0) {
2080 bios_lock_shadow_ram();
2082 BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr
);
2083 if (bios_table_cur_addr
> bios_table_end_addr
)
2084 BX_PANIC("bios_table_end_addr overflow!\n");