1 /////////////////////////////////////////////////////////////////////////
2 // $Id: rombios32.c,v 1.11 2007/08/03 13:56:13 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // 32 bit Bochs BIOS init code
6 // Copyright (C) 2006 Fabrice Bellard
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 typedef signed char int8_t;
27 typedef short int16_t;
29 typedef long long int64_t;
30 typedef unsigned char uint8_t;
31 typedef unsigned short uint16_t;
32 typedef unsigned int uint32_t;
33 typedef unsigned long long uint64_t;
35 /* if true, put the MP float table and ACPI RSDT in EBDA and the MP
36 table in RAM. Unfortunately, Linux has bugs with that, so we prefer
37 to modify the BIOS in shadow RAM */
38 //#define BX_USE_EBDA_TABLES
40 /* define it if the (emulated) hardware supports SMM mode */
43 #define cpuid(index, eax, ebx, ecx, edx) \
44 asm volatile ("cpuid" \
45 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
48 #define wbinvd() asm volatile("wbinvd")
50 #define CPUID_APIC (1 << 9)
52 #define APIC_BASE ((uint8_t *)0xfee00000)
53 #define APIC_ICR_LOW 0x300
54 #define APIC_SVR 0x0F0
56 #define APIC_LVT3 0x370
59 #define PCI_ISA_IRQ_MASK 0x0e20U
61 #define APIC_ENABLED 0x0100
63 #define AP_BOOT_ADDR 0x10000
65 #define MPTABLE_MAX_SIZE 0x00002000
66 #define SMI_CMD_IO_ADDR 0xb2
68 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
70 static inline void outl(int addr
, int val
)
72 asm volatile ("outl %1, %w0" : : "d" (addr
), "a" (val
));
75 static inline void outw(int addr
, int val
)
77 asm volatile ("outw %w1, %w0" : : "d" (addr
), "a" (val
));
80 static inline void outb(int addr
, int val
)
82 asm volatile ("outb %b1, %w0" : : "d" (addr
), "a" (val
));
85 static inline uint32_t inl(int addr
)
88 asm volatile ("inl %w1, %0" : "=a" (val
) : "d" (addr
));
92 static inline uint16_t inw(int addr
)
95 asm volatile ("inw %w1, %w0" : "=a" (val
) : "d" (addr
));
99 static inline uint8_t inb(int addr
)
102 asm volatile ("inb %w1, %b0" : "=a" (val
) : "d" (addr
));
106 static inline void writel(void *addr
, uint32_t val
)
108 *(volatile uint32_t *)addr
= val
;
111 static inline void writew(void *addr
, uint16_t val
)
113 *(volatile uint16_t *)addr
= val
;
116 static inline void writeb(void *addr
, uint8_t val
)
118 *(volatile uint8_t *)addr
= val
;
121 static inline uint32_t readl(const void *addr
)
123 return *(volatile const uint32_t *)addr
;
126 static inline uint16_t readw(const void *addr
)
128 return *(volatile const uint16_t *)addr
;
131 static inline uint8_t readb(const void *addr
)
133 return *(volatile const uint8_t *)addr
;
136 static inline void putc(int c
)
141 static inline int isdigit(int c
)
143 return c
>= '0' && c
<= '9';
146 void *memset(void *d1
, int val
, size_t len
)
156 void *memcpy(void *d1
, const void *s1
, size_t len
)
159 const uint8_t *s
= s1
;
167 void *memmove(void *d1
, const void *s1
, size_t len
)
170 const uint8_t *s
= s1
;
186 size_t strlen(const char *s
)
189 for(s1
= s
; *s1
!= '\0'; s1
++);
193 /* from BSD ppp sources */
194 int vsnprintf(char *buf
, int buflen
, const char *fmt
, va_list args
)
197 int width
, prec
, fillch
;
199 unsigned long val
= 0;
203 static const char hexchars
[] = "0123456789abcdef";
208 for (f
= fmt
; *f
!= '%' && *f
!= 0; ++f
)
214 memcpy(buf
, fmt
, len
);
229 width
= va_arg(args
, int);
233 width
= width
* 10 + c
- '0';
240 prec
= va_arg(args
, int);
244 prec
= prec
* 10 + c
- '0';
263 i
= va_arg(args
, int);
272 val
= va_arg(args
, unsigned int);
277 val
= va_arg(args
, unsigned int);
281 val
= (unsigned long) va_arg(args
, void *);
286 str
= va_arg(args
, char *);
289 num
[0] = va_arg(args
, int);
296 --fmt
; /* so %z outputs %z etc. */
301 str
= num
+ sizeof(num
);
303 while (str
> num
+ neg
) {
304 *--str
= hexchars
[val
% base
];
306 if (--prec
<= 0 && val
== 0)
318 len
= num
+ sizeof(num
) - 1 - str
;
321 if (prec
> 0 && len
> prec
)
327 if ((n
= width
- len
) > 0) {
335 memcpy(buf
, str
, len
);
343 void bios_printf(int flags
, const char *fmt
, ...)
349 if ((flags
& BIOS_PRINTF_DEBHALT
) == BIOS_PRINTF_DEBHALT
)
350 outb(PANIC_PORT2
, 0x00);
353 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
363 for(i
= 0; i
< n
; i
++) {
365 /* approximative ! */
366 for(j
= 0; j
< 1000000; j
++);
371 r1
= inb(0x61) & 0x10;
373 r2
= inb(0x61) & 0x10;
385 uint32_t cpuid_signature
;
386 uint32_t cpuid_features
;
387 uint32_t cpuid_ext_features
;
388 unsigned long ram_size
;
389 uint8_t bios_uuid
[16];
390 #ifdef BX_USE_EBDA_TABLES
391 unsigned long ebda_cur_addr
;
394 uint32_t pm_io_base
, smb_io_base
;
396 unsigned long bios_table_cur_addr
;
397 unsigned long bios_table_end_addr
;
399 void uuid_probe(void)
402 uint32_t eax
, ebx
, ecx
, edx
;
404 // check if backdoor port exists
405 asm volatile ("outl %%eax, %%dx"
406 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
407 : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
408 if (ebx
== 0x564d5868) {
409 uint32_t *uuid_ptr
= (uint32_t *)bios_uuid
;
411 asm volatile ("outl %%eax, %%dx"
412 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
413 : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
422 memset(bios_uuid
, 0, 16);
428 uint32_t eax
, ebx
, ecx
, edx
;
429 cpuid(1, eax
, ebx
, ecx
, edx
);
430 cpuid_signature
= eax
;
431 cpuid_features
= edx
;
432 cpuid_ext_features
= ecx
;
435 static int cmos_readb(int addr
)
443 if (cmos_readb(0x34) | cmos_readb(0x35))
444 ram_size
= (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
447 ram_size
= (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
448 #ifdef BX_USE_EBDA_TABLES
449 ebda_cur_addr
= ((*(uint16_t *)(0x40e)) << 4) + 0x380;
451 BX_INFO("ram_size=0x%08lx\n", ram_size
);
454 /****************************************************/
457 extern uint8_t smp_ap_boot_code_start
;
458 extern uint8_t smp_ap_boot_code_end
;
460 /* find the number of CPUs by launching a SIPI to them */
463 uint32_t val
, sipi_vector
;
466 if (cpuid_features
& CPUID_APIC
) {
468 /* enable local APIC */
469 val
= readl(APIC_BASE
+ APIC_SVR
);
471 writel(APIC_BASE
+ APIC_SVR
, val
);
473 writew((void *)CPU_COUNT_ADDR
, 1);
474 /* copy AP boot code */
475 memcpy((void *)AP_BOOT_ADDR
, &smp_ap_boot_code_start
,
476 &smp_ap_boot_code_end
- &smp_ap_boot_code_start
);
479 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4500);
480 sipi_vector
= AP_BOOT_ADDR
>> 12;
481 writel(APIC_BASE
+ APIC_ICR_LOW
, 0x000C4600 | sipi_vector
);
483 "xor %%eax, %%eax \n\t"
484 "xor %%edx, %%edx \n\t"
485 "mov $0x10, %%ecx \n\t"
487 : : : "eax", "ecx", "edx");
492 while (cmos_readb(0x5f) + 1 != readw((void *)CPU_COUNT_ADDR
))
496 smp_cpus
= readw((void *)CPU_COUNT_ADDR
);
498 BX_INFO("Found %d cpu(s)\n", smp_cpus
);
501 /****************************************************/
504 #define PCI_ADDRESS_SPACE_MEM 0x00
505 #define PCI_ADDRESS_SPACE_IO 0x01
506 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
508 #define PCI_ROM_SLOT 6
509 #define PCI_NUM_REGIONS 7
511 #define PCI_DEVICES_MAX 64
513 #define PCI_VENDOR_ID 0x00 /* 16 bits */
514 #define PCI_DEVICE_ID 0x02 /* 16 bits */
515 #define PCI_COMMAND 0x04 /* 16 bits */
516 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
517 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
518 #define PCI_CLASS_DEVICE 0x0a /* Device class */
519 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
520 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
521 #define PCI_MIN_GNT 0x3e /* 8 bits */
522 #define PCI_MAX_LAT 0x3f /* 8 bits */
524 typedef struct PCIDevice
{
529 static uint32_t pci_bios_io_addr
;
530 static uint32_t pci_bios_mem_addr
;
531 static uint32_t pci_bios_bigmem_addr
;
532 /* host irqs corresponding to PCI irqs A-D */
533 static uint8_t pci_irqs
[4] = { 10, 10, 11, 11 };
534 static PCIDevice i440_pcidev
;
536 static void pci_config_writel(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
538 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
542 static void pci_config_writew(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
544 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
545 outw(0xcfc + (addr
& 2), val
);
548 static void pci_config_writeb(PCIDevice
*d
, uint32_t addr
, uint32_t val
)
550 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
551 outb(0xcfc + (addr
& 3), val
);
554 static uint32_t pci_config_readl(PCIDevice
*d
, uint32_t addr
)
556 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
560 static uint32_t pci_config_readw(PCIDevice
*d
, uint32_t addr
)
562 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
563 return inw(0xcfc + (addr
& 2));
566 static uint32_t pci_config_readb(PCIDevice
*d
, uint32_t addr
)
568 outl(0xcf8, 0x80000000 | (d
->bus
<< 16) | (d
->devfn
<< 8) | (addr
& 0xfc));
569 return inb(0xcfc + (addr
& 3));
572 static void pci_set_io_region_addr(PCIDevice
*d
, int region_num
, uint32_t addr
)
575 uint32_t ofs
, old_addr
;
577 if ( region_num
== PCI_ROM_SLOT
) {
580 ofs
= 0x10 + region_num
* 4;
583 old_addr
= pci_config_readl(d
, ofs
);
585 pci_config_writel(d
, ofs
, addr
);
586 BX_INFO("region %d: 0x%08x\n", region_num
, addr
);
588 /* enable memory mappings */
589 cmd
= pci_config_readw(d
, PCI_COMMAND
);
590 if ( region_num
== PCI_ROM_SLOT
)
592 else if (old_addr
& PCI_ADDRESS_SPACE_IO
)
596 pci_config_writew(d
, PCI_COMMAND
, cmd
);
599 /* return the global irq number corresponding to a given device irq
600 pin. We could also use the bus number to have a more precise
602 static int pci_slot_get_pirq(PCIDevice
*pci_dev
, int irq_num
)
605 slot_addend
= (pci_dev
->devfn
>> 3) - 1;
606 return (irq_num
+ slot_addend
) & 3;
609 static int find_bios_table_area(void)
612 for(addr
= 0xf0000; addr
< 0x100000; addr
+= 16) {
613 if (*(uint32_t *)addr
== 0xaafb4442) {
614 bios_table_cur_addr
= addr
+ 8;
615 bios_table_end_addr
= bios_table_cur_addr
+ *(uint32_t *)(addr
+ 4);
616 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
617 bios_table_cur_addr
, bios_table_end_addr
);
624 static void bios_shadow_init(PCIDevice
*d
)
628 if (find_bios_table_area() < 0)
631 /* remap the BIOS to shadow RAM an keep it read/write while we
632 are writing tables */
633 v
= pci_config_readb(d
, 0x59);
635 pci_config_writeb(d
, 0x59, v
);
636 memcpy((void *)BIOS_TMP_STORAGE
, (void *)0x000f0000, 0x10000);
638 pci_config_writeb(d
, 0x59, v
);
639 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE
, 0x10000);
644 static void bios_lock_shadow_ram(void)
646 PCIDevice
*d
= &i440_pcidev
;
650 v
= pci_config_readb(d
, 0x59);
651 v
= (v
& 0x0f) | (0x10);
652 pci_config_writeb(d
, 0x59, v
);
655 static void pci_bios_init_bridges(PCIDevice
*d
)
657 uint16_t vendor_id
, device_id
;
659 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
660 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
662 if (vendor_id
== 0x8086 && device_id
== 0x7000) {
670 for(i
= 0; i
< 4; i
++) {
672 /* set to trigger level */
673 elcr
[irq
>> 3] |= (1 << (irq
& 7));
674 /* activate irq remapping in PIIX */
675 pci_config_writeb(d
, 0x60 + i
, irq
);
677 outb(0x4d0, elcr
[0]);
678 outb(0x4d1, elcr
[1]);
679 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
681 } else if (vendor_id
== 0x8086 && device_id
== 0x1237) {
682 /* i440 PCI bridge */
687 extern uint8_t smm_relocation_start
, smm_relocation_end
;
688 extern uint8_t smm_code_start
, smm_code_end
;
691 static void smm_init(PCIDevice
*d
)
695 /* check if SMM init is already done */
696 value
= pci_config_readl(d
, 0x58);
697 if ((value
& (1 << 25)) == 0) {
699 /* copy the SMM relocation code */
700 memcpy((void *)0x38000, &smm_relocation_start
,
701 &smm_relocation_end
- &smm_relocation_start
);
703 /* enable SMI generation when writing to the APMC register */
704 pci_config_writel(d
, 0x58, value
| (1 << 25));
706 /* init APM status port */
709 /* raise an SMI interrupt */
712 /* wait until SMM code executed */
713 while (inb(0xb3) != 0x00);
715 /* enable the SMM memory window */
716 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x48);
718 /* copy the SMM code */
719 memcpy((void *)0xa8000, &smm_code_start
,
720 &smm_code_end
- &smm_code_start
);
723 /* close the SMM memory window and enable normal SMM */
724 pci_config_writeb(&i440_pcidev
, 0x72, 0x02 | 0x08);
729 static void pci_bios_init_device(PCIDevice
*d
)
733 int i
, pin
, pic_irq
, vendor_id
, device_id
;
735 class = pci_config_readw(d
, PCI_CLASS_DEVICE
);
736 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
737 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
738 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
739 d
->bus
, d
->devfn
, vendor_id
, device_id
);
742 if (vendor_id
== 0x8086 && device_id
== 0x7010) {
744 pci_config_writew(d
, 0x40, 0x8000); // enable IDE0
745 pci_config_writew(d
, 0x42, 0x8000); // enable IDE1
748 /* IDE: we map it as in ISA mode */
749 pci_set_io_region_addr(d
, 0, 0x1f0);
750 pci_set_io_region_addr(d
, 1, 0x3f4);
751 pci_set_io_region_addr(d
, 2, 0x170);
752 pci_set_io_region_addr(d
, 3, 0x374);
756 if (vendor_id
!= 0x1234)
758 /* VGA: map frame buffer to default Bochs VBE address */
759 pci_set_io_region_addr(d
, 0, 0xE0000000);
763 if (vendor_id
== 0x1014) {
765 if (device_id
== 0x0046 || device_id
== 0xFFFF) {
767 pci_set_io_region_addr(d
, 0, 0x80800000 + 0x00040000);
772 if (vendor_id
== 0x0106b &&
773 (device_id
== 0x0017 || device_id
== 0x0022)) {
775 pci_set_io_region_addr(d
, 0, 0x80800000);
780 /* default memory mappings */
781 for(i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
785 if (i
== PCI_ROM_SLOT
)
789 pci_config_writel(d
, ofs
, 0xffffffff);
790 val
= pci_config_readl(d
, ofs
);
792 size
= (~(val
& ~0xf)) + 1;
793 if (val
& PCI_ADDRESS_SPACE_IO
)
794 paddr
= &pci_bios_io_addr
;
795 else if (size
>= 0x04000000)
796 paddr
= &pci_bios_bigmem_addr
;
798 paddr
= &pci_bios_mem_addr
;
799 *paddr
= (*paddr
+ size
- 1) & ~(size
- 1);
800 pci_set_io_region_addr(d
, i
, *paddr
);
807 /* map the interrupt */
808 pin
= pci_config_readb(d
, PCI_INTERRUPT_PIN
);
810 pin
= pci_slot_get_pirq(d
, pin
- 1);
811 pic_irq
= pci_irqs
[pin
];
812 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, pic_irq
);
815 if (vendor_id
== 0x8086 && device_id
== 0x7113) {
816 /* PIIX4 Power Management device (for ACPI) */
818 // acpi sci is hardwired to 9
819 pci_config_writeb(d
, PCI_INTERRUPT_LINE
, 9);
821 pm_io_base
= PM_IO_BASE
;
822 pci_config_writel(d
, 0x40, pm_io_base
| 1);
823 pci_config_writeb(d
, 0x80, 0x01); /* enable PM io space */
824 smb_io_base
= SMB_IO_BASE
;
825 pci_config_writel(d
, 0x90, smb_io_base
| 1);
826 pci_config_writeb(d
, 0xd2, 0x09); /* enable SMBus io space */
827 pm_sci_int
= pci_config_readb(d
, PCI_INTERRUPT_LINE
);
835 void pci_for_each_device(void (*init_func
)(PCIDevice
*d
))
837 PCIDevice d1
, *d
= &d1
;
839 uint16_t vendor_id
, device_id
;
841 for(bus
= 0; bus
< 1; bus
++) {
842 for(devfn
= 0; devfn
< 256; devfn
++) {
845 vendor_id
= pci_config_readw(d
, PCI_VENDOR_ID
);
846 device_id
= pci_config_readw(d
, PCI_DEVICE_ID
);
847 if (vendor_id
!= 0xffff || device_id
!= 0xffff) {
854 void pci_bios_init(void)
856 pci_bios_io_addr
= 0xc000;
857 pci_bios_mem_addr
= 0xf0000000;
858 pci_bios_bigmem_addr
= ram_size
;
859 if (pci_bios_bigmem_addr
< 0x90000000)
860 pci_bios_bigmem_addr
= 0x90000000;
862 pci_for_each_device(pci_bios_init_bridges
);
864 pci_for_each_device(pci_bios_init_device
);
867 /****************************************************/
868 /* Multi Processor table init */
870 static void putb(uint8_t **pp
, int val
)
878 static void putstr(uint8_t **pp
, const char *str
)
887 static void putle16(uint8_t **pp
, int val
)
896 static void putle32(uint8_t **pp
, int val
)
907 static int mpf_checksum(const uint8_t *data
, int len
)
911 for(i
= 0; i
< len
; i
++)
916 static unsigned long align(unsigned long addr
, unsigned long v
)
918 return (addr
+ v
- 1) & ~(v
- 1);
921 static void mptable_init(void)
923 uint8_t *mp_config_table
, *q
, *float_pointer_struct
;
924 int ioapic_id
, i
, len
;
925 int mp_config_table_size
;
932 #ifdef BX_USE_EBDA_TABLES
933 mp_config_table
= (uint8_t *)(ram_size
- ACPI_DATA_SIZE
- MPTABLE_MAX_SIZE
);
935 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
936 mp_config_table
= (uint8_t *)bios_table_cur_addr
;
939 putstr(&q
, "PCMP"); /* "PCMP signature */
940 putle16(&q
, 0); /* table length (patched later) */
941 putb(&q
, 4); /* spec rev */
942 putb(&q
, 0); /* checksum (patched later) */
944 putstr(&q
, "QEMUCPU "); /* OEM id */
946 putstr(&q
, "BOCHSCPU");
948 putstr(&q
, "0.1 "); /* vendor id */
949 putle32(&q
, 0); /* OEM table ptr */
950 putle16(&q
, 0); /* OEM table size */
951 putle16(&q
, MAX_CPUS
+ 18); /* entry count */
952 putle32(&q
, 0xfee00000); /* local APIC addr */
953 putle16(&q
, 0); /* ext table length */
954 putb(&q
, 0); /* ext table checksum */
955 putb(&q
, 0); /* reserved */
957 for(i
= 0; i
< MAX_CPUS
; i
++) {
958 putb(&q
, 0); /* entry type = processor */
959 putb(&q
, i
); /* APIC id */
960 putb(&q
, 0x11); /* local APIC version number */
962 putb(&q
, 3); /* cpu flags: enabled, bootstrap cpu */
963 else if ( i
< smp_cpus
)
964 putb(&q
, 1); /* cpu flags: enabled */
966 putb(&q
, 0); /* cpu flags: disabled */
967 putb(&q
, 0); /* cpu signature */
971 putle16(&q
, 0x201); /* feature flags */
974 putle16(&q
, 0); /* reserved */
981 putb(&q
, 1); /* entry type = bus */
982 putb(&q
, 0); /* bus ID */
986 ioapic_id
= smp_cpus
;
987 putb(&q
, 2); /* entry type = I/O APIC */
988 putb(&q
, ioapic_id
); /* apic ID */
989 putb(&q
, 0x11); /* I/O APIC version number */
990 putb(&q
, 1); /* enable */
991 putle32(&q
, 0xfec00000); /* I/O APIC addr */
994 for(i
= 0; i
< 16; i
++) {
995 putb(&q
, 3); /* entry type = I/O interrupt */
996 putb(&q
, 0); /* interrupt type = vectored interrupt */
997 putb(&q
, 0); /* flags: po=0, el=0 */
999 putb(&q
, 0); /* source bus ID = ISA */
1000 putb(&q
, i
); /* source bus IRQ */
1001 putb(&q
, ioapic_id
); /* dest I/O APIC ID */
1002 putb(&q
, i
); /* dest I/O APIC interrupt in */
1005 len
= q
- mp_config_table
;
1006 mp_config_table
[4] = len
;
1007 mp_config_table
[5] = len
>> 8;
1009 mp_config_table
[7] = -mpf_checksum(mp_config_table
, q
- mp_config_table
);
1011 mp_config_table_size
= q
- mp_config_table
;
1013 #ifndef BX_USE_EBDA_TABLES
1014 bios_table_cur_addr
+= mp_config_table_size
;
1017 /* floating pointer structure */
1018 #ifdef BX_USE_EBDA_TABLES
1019 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1020 float_pointer_struct
= (uint8_t *)ebda_cur_addr
;
1022 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1023 float_pointer_struct
= (uint8_t *)bios_table_cur_addr
;
1025 q
= float_pointer_struct
;
1027 /* pointer to MP config table */
1028 putle32(&q
, (unsigned long)mp_config_table
);
1030 putb(&q
, 1); /* length in 16 byte units */
1031 putb(&q
, 4); /* MP spec revision */
1032 putb(&q
, 0); /* checksum (patched later) */
1033 putb(&q
, 0); /* MP feature byte 1 */
1039 float_pointer_struct
[10] =
1040 -mpf_checksum(float_pointer_struct
, q
- float_pointer_struct
);
1041 #ifdef BX_USE_EBDA_TABLES
1042 ebda_cur_addr
+= (q
- float_pointer_struct
);
1044 bios_table_cur_addr
+= (q
- float_pointer_struct
);
1046 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
1047 (unsigned long)float_pointer_struct
,
1048 (unsigned long)mp_config_table
,
1049 mp_config_table_size
);
1052 /****************************************************/
1053 /* ACPI tables init */
1055 /* Table structure from Linux kernel (the ACPI tables are under the
1058 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
1059 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
1060 uint32_t length; /* Length of table, in bytes, including header */\
1061 uint8_t revision; /* ACPI Specification minor version # */\
1062 uint8_t checksum; /* To make sum of entire table == 0 */\
1063 uint8_t oem_id [6]; /* OEM identification */\
1064 uint8_t oem_table_id [8]; /* OEM table identification */\
1065 uint32_t oem_revision; /* OEM revision number */\
1066 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
1067 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1070 struct acpi_table_header
/* ACPI common table header */
1072 ACPI_TABLE_HEADER_DEF
1075 struct rsdp_descriptor
/* Root System Descriptor Pointer */
1077 uint8_t signature
[8]; /* ACPI signature, contains "RSD PTR " */
1078 uint8_t checksum
; /* To make sum of struct == 0 */
1079 uint8_t oem_id
[6]; /* OEM identification */
1080 uint8_t revision
; /* Must be 0 for 1.0, 2 for 2.0 */
1081 uint32_t rsdt_physical_address
; /* 32-bit physical address of RSDT */
1082 uint32_t length
; /* XSDT Length in bytes including hdr */
1083 uint64_t xsdt_physical_address
; /* 64-bit physical address of XSDT */
1084 uint8_t extended_checksum
; /* Checksum of entire table */
1085 uint8_t reserved
[3]; /* Reserved field must be 0 */
1089 * ACPI 1.0 Root System Description Table (RSDT)
1091 struct rsdt_descriptor_rev1
1093 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1094 uint32_t table_offset_entry
[2]; /* Array of pointers to other */
1099 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1101 struct facs_descriptor_rev1
1103 uint8_t signature
[4]; /* ACPI Signature */
1104 uint32_t length
; /* Length of structure, in bytes */
1105 uint32_t hardware_signature
; /* Hardware configuration signature */
1106 uint32_t firmware_waking_vector
; /* ACPI OS waking vector */
1107 uint32_t global_lock
; /* Global Lock */
1108 uint32_t S4bios_f
: 1; /* Indicates if S4BIOS support is present */
1109 uint32_t reserved1
: 31; /* Must be 0 */
1110 uint8_t resverved3
[40]; /* Reserved - must be zero */
1115 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1117 struct fadt_descriptor_rev1
1119 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1120 uint32_t firmware_ctrl
; /* Physical address of FACS */
1121 uint32_t dsdt
; /* Physical address of DSDT */
1122 uint8_t model
; /* System Interrupt Model */
1123 uint8_t reserved1
; /* Reserved */
1124 uint16_t sci_int
; /* System vector of SCI interrupt */
1125 uint32_t smi_cmd
; /* Port address of SMI command port */
1126 uint8_t acpi_enable
; /* Value to write to smi_cmd to enable ACPI */
1127 uint8_t acpi_disable
; /* Value to write to smi_cmd to disable ACPI */
1128 uint8_t S4bios_req
; /* Value to write to SMI CMD to enter S4BIOS state */
1129 uint8_t reserved2
; /* Reserved - must be zero */
1130 uint32_t pm1a_evt_blk
; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1131 uint32_t pm1b_evt_blk
; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1132 uint32_t pm1a_cnt_blk
; /* Port address of Power Mgt 1a Control Reg Blk */
1133 uint32_t pm1b_cnt_blk
; /* Port address of Power Mgt 1b Control Reg Blk */
1134 uint32_t pm2_cnt_blk
; /* Port address of Power Mgt 2 Control Reg Blk */
1135 uint32_t pm_tmr_blk
; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1136 uint32_t gpe0_blk
; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1137 uint32_t gpe1_blk
; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1138 uint8_t pm1_evt_len
; /* Byte length of ports at pm1_x_evt_blk */
1139 uint8_t pm1_cnt_len
; /* Byte length of ports at pm1_x_cnt_blk */
1140 uint8_t pm2_cnt_len
; /* Byte Length of ports at pm2_cnt_blk */
1141 uint8_t pm_tmr_len
; /* Byte Length of ports at pm_tm_blk */
1142 uint8_t gpe0_blk_len
; /* Byte Length of ports at gpe0_blk */
1143 uint8_t gpe1_blk_len
; /* Byte Length of ports at gpe1_blk */
1144 uint8_t gpe1_base
; /* Offset in gpe model where gpe1 events start */
1145 uint8_t reserved3
; /* Reserved */
1146 uint16_t plvl2_lat
; /* Worst case HW latency to enter/exit C2 state */
1147 uint16_t plvl3_lat
; /* Worst case HW latency to enter/exit C3 state */
1148 uint16_t flush_size
; /* Size of area read to flush caches */
1149 uint16_t flush_stride
; /* Stride used in flushing caches */
1150 uint8_t duty_offset
; /* Bit location of duty cycle field in p_cnt reg */
1151 uint8_t duty_width
; /* Bit width of duty cycle field in p_cnt reg */
1152 uint8_t day_alrm
; /* Index to day-of-month alarm in RTC CMOS RAM */
1153 uint8_t mon_alrm
; /* Index to month-of-year alarm in RTC CMOS RAM */
1154 uint8_t century
; /* Index to century in RTC CMOS RAM */
1155 uint8_t reserved4
; /* Reserved */
1156 uint8_t reserved4a
; /* Reserved */
1157 uint8_t reserved4b
; /* Reserved */
1159 uint32_t wb_invd
: 1; /* The wbinvd instruction works properly */
1160 uint32_t wb_invd_flush
: 1; /* The wbinvd flushes but does not invalidate */
1161 uint32_t proc_c1
: 1; /* All processors support C1 state */
1162 uint32_t plvl2_up
: 1; /* C2 state works on MP system */
1163 uint32_t pwr_button
: 1; /* Power button is handled as a generic feature */
1164 uint32_t sleep_button
: 1; /* Sleep button is handled as a generic feature, or not present */
1165 uint32_t fixed_rTC
: 1; /* RTC wakeup stat not in fixed register space */
1166 uint32_t rtcs4
: 1; /* RTC wakeup stat not possible from S4 */
1167 uint32_t tmr_val_ext
: 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1168 uint32_t reserved5
: 23; /* Reserved - must be zero */
1175 * MADT values and structures
1178 /* Values for MADT PCATCompat */
1181 #define MULTIPLE_APIC 1
1186 struct multiple_apic_table
1188 ACPI_TABLE_HEADER_DEF
/* ACPI common table header */
1189 uint32_t local_apic_address
; /* Physical address of local APIC */
1191 uint32_t PCATcompat
: 1; /* A one indicates system also has dual 8259s */
1192 uint32_t reserved1
: 31;
1199 /* Values for Type in APIC_HEADER_DEF */
1201 #define APIC_PROCESSOR 0
1203 #define APIC_XRUPT_OVERRIDE 2
1205 #define APIC_LOCAL_NMI 4
1206 #define APIC_ADDRESS_OVERRIDE 5
1207 #define APIC_IO_SAPIC 6
1208 #define APIC_LOCAL_SAPIC 7
1209 #define APIC_XRUPT_SOURCE 8
1210 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1213 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1215 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1219 /* Sub-structures for MADT */
1221 struct madt_processor_apic
1224 uint8_t processor_id
; /* ACPI processor id */
1225 uint8_t local_apic_id
; /* Processor's local APIC id */
1227 uint32_t processor_enabled
: 1; /* Processor is usable if set */
1228 uint32_t reserved2
: 31; /* Reserved, must be zero */
1237 uint8_t io_apic_id
; /* I/O APIC ID */
1238 uint8_t reserved
; /* Reserved - must be zero */
1239 uint32_t address
; /* APIC physical address */
1240 uint32_t interrupt
; /* Global system interrupt where INTI
1244 struct madt_intsrcovr
{
1250 } __attribute__((packed
));
1252 #include "acpi-dsdt.hex"
1254 static inline uint16_t cpu_to_le16(uint16_t x
)
1259 static inline uint32_t cpu_to_le32(uint32_t x
)
1264 static int acpi_checksum(const uint8_t *data
, int len
)
1268 for(i
= 0; i
< len
; i
++)
1270 return (-sum
) & 0xff;
1273 static void acpi_build_table_header(struct acpi_table_header
*h
,
1274 char *sig
, int len
, uint8_t rev
)
1276 memcpy(h
->signature
, sig
, 4);
1277 h
->length
= cpu_to_le32(len
);
1280 memcpy(h
->oem_id
, "QEMU ", 6);
1281 memcpy(h
->oem_table_id
, "QEMU", 4);
1283 memcpy(h
->oem_id
, "BOCHS ", 6);
1284 memcpy(h
->oem_table_id
, "BXPC", 4);
1286 memcpy(h
->oem_table_id
+ 4, sig
, 4);
1287 h
->oem_revision
= cpu_to_le32(1);
1289 memcpy(h
->asl_compiler_id
, "QEMU", 4);
1291 memcpy(h
->asl_compiler_id
, "BXPC", 4);
1293 h
->asl_compiler_revision
= cpu_to_le32(1);
1294 h
->checksum
= acpi_checksum((void *)h
, len
);
1297 /* base_addr must be a multiple of 4KB */
1298 void acpi_bios_init(void)
1300 struct rsdp_descriptor
*rsdp
;
1301 struct rsdt_descriptor_rev1
*rsdt
;
1302 struct fadt_descriptor_rev1
*fadt
;
1303 struct facs_descriptor_rev1
*facs
;
1304 struct multiple_apic_table
*madt
;
1306 uint32_t base_addr
, rsdt_addr
, fadt_addr
, addr
, facs_addr
, dsdt_addr
;
1307 uint32_t acpi_tables_size
, madt_addr
, madt_size
;
1310 /* reserve memory space for tables */
1311 #ifdef BX_USE_EBDA_TABLES
1312 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1313 rsdp
= (void *)(ebda_cur_addr
);
1314 ebda_cur_addr
+= sizeof(*rsdp
);
1316 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1317 rsdp
= (void *)(bios_table_cur_addr
);
1318 bios_table_cur_addr
+= sizeof(*rsdp
);
1321 addr
= base_addr
= ram_size
- ACPI_DATA_SIZE
;
1323 rsdt
= (void *)(addr
);
1324 addr
+= sizeof(*rsdt
);
1327 fadt
= (void *)(addr
);
1328 addr
+= sizeof(*fadt
);
1330 /* XXX: FACS should be in RAM */
1331 addr
= (addr
+ 63) & ~63; /* 64 byte alignment for FACS */
1333 facs
= (void *)(addr
);
1334 addr
+= sizeof(*facs
);
1337 dsdt
= (void *)(addr
);
1338 addr
+= sizeof(AmlCode
);
1340 addr
= (addr
+ 7) & ~7;
1342 madt_size
= sizeof(*madt
) +
1343 sizeof(struct madt_processor_apic
) * MAX_CPUS
+
1344 sizeof(struct madt_io_apic
);
1345 madt
= (void *)(addr
);
1348 acpi_tables_size
= addr
- base_addr
;
1350 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1351 (unsigned long)rsdp
,
1352 (unsigned long)rsdt
, acpi_tables_size
);
1355 memset(rsdp
, 0, sizeof(*rsdp
));
1356 memcpy(rsdp
->signature
, "RSD PTR ", 8);
1358 memcpy(rsdp
->oem_id
, "QEMU ", 6);
1360 memcpy(rsdp
->oem_id
, "BOCHS ", 6);
1362 rsdp
->rsdt_physical_address
= cpu_to_le32(rsdt_addr
);
1363 rsdp
->checksum
= acpi_checksum((void *)rsdp
, 20);
1366 memset(rsdt
, 0, sizeof(*rsdt
));
1367 rsdt
->table_offset_entry
[0] = cpu_to_le32(fadt_addr
);
1368 rsdt
->table_offset_entry
[1] = cpu_to_le32(madt_addr
);
1369 acpi_build_table_header((struct acpi_table_header
*)rsdt
,
1370 "RSDT", sizeof(*rsdt
), 1);
1373 memset(fadt
, 0, sizeof(*fadt
));
1374 fadt
->firmware_ctrl
= cpu_to_le32(facs_addr
);
1375 fadt
->dsdt
= cpu_to_le32(dsdt_addr
);
1377 fadt
->reserved1
= 0;
1378 fadt
->sci_int
= cpu_to_le16(pm_sci_int
);
1379 fadt
->smi_cmd
= cpu_to_le32(SMI_CMD_IO_ADDR
);
1380 fadt
->acpi_enable
= 0xf1;
1381 fadt
->acpi_disable
= 0xf0;
1382 fadt
->pm1a_evt_blk
= cpu_to_le32(pm_io_base
);
1383 fadt
->pm1a_cnt_blk
= cpu_to_le32(pm_io_base
+ 0x04);
1384 fadt
->pm_tmr_blk
= cpu_to_le32(pm_io_base
+ 0x08);
1385 fadt
->pm1_evt_len
= 4;
1386 fadt
->pm1_cnt_len
= 2;
1387 fadt
->pm_tmr_len
= 4;
1388 fadt
->plvl2_lat
= cpu_to_le16(0x0fff); // C2 state not supported
1389 fadt
->plvl3_lat
= cpu_to_le16(0x0fff); // C3 state not supported
1390 fadt
->gpe0_blk
= cpu_to_le32(0xafe0);
1391 fadt
->gpe0_blk_len
= 4;
1392 /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
1393 fadt
->flags
= cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
1394 acpi_build_table_header((struct acpi_table_header
*)fadt
, "FACP",
1398 memset(facs
, 0, sizeof(*facs
));
1399 memcpy(facs
->signature
, "FACS", 4);
1400 facs
->length
= cpu_to_le32(sizeof(*facs
));
1403 memcpy(dsdt
, AmlCode
, sizeof(AmlCode
));
1407 struct madt_processor_apic
*apic
;
1408 struct madt_io_apic
*io_apic
;
1409 struct madt_intsrcovr
*intsrcovr
;
1411 memset(madt
, 0, madt_size
);
1412 madt
->local_apic_address
= cpu_to_le32(0xfee00000);
1413 madt
->flags
= cpu_to_le32(1);
1414 apic
= (void *)(madt
+ 1);
1415 for(i
=0;i
<MAX_CPUS
;i
++) {
1416 apic
->type
= APIC_PROCESSOR
;
1417 apic
->length
= sizeof(*apic
);
1418 apic
->processor_id
= i
;
1419 apic
->local_apic_id
= i
;
1421 apic
->flags
= cpu_to_le32(1);
1426 io_apic
= (void *)apic
;
1427 io_apic
->type
= APIC_IO
;
1428 io_apic
->length
= sizeof(*io_apic
);
1429 io_apic
->io_apic_id
= smp_cpus
;
1430 io_apic
->address
= cpu_to_le32(0xfec00000);
1431 io_apic
->interrupt
= cpu_to_le32(0);
1433 intsrcovr
= (struct madt_intsrcovr
*)(io_apic
+ 1);
1434 for ( i
= 0; i
< 16; i
++ ) {
1435 if ( PCI_ISA_IRQ_MASK
& (1U << i
) ) {
1436 memset(intsrcovr
, 0, sizeof(*intsrcovr
));
1437 intsrcovr
->type
= APIC_XRUPT_OVERRIDE
;
1438 intsrcovr
->length
= sizeof(*intsrcovr
);
1439 intsrcovr
->source
= i
;
1441 intsrcovr
->flags
= 0xd; /* active high, level triggered */
1443 /* No need for a INT source override structure. */
1447 madt_size
+= sizeof(struct madt_intsrcovr
);
1449 acpi_build_table_header((struct acpi_table_header
*)madt
,
1450 "APIC", madt_size
, 1);
1454 /* SMBIOS entry point -- must be written to a 16-bit aligned address
1455 between 0xf0000 and 0xfffff.
1457 struct smbios_entry_point
{
1458 char anchor_string
[4];
1461 uint8_t smbios_major_version
;
1462 uint8_t smbios_minor_version
;
1463 uint16_t max_structure_size
;
1464 uint8_t entry_point_revision
;
1465 uint8_t formatted_area
[5];
1466 char intermediate_anchor_string
[5];
1467 uint8_t intermediate_checksum
;
1468 uint16_t structure_table_length
;
1469 uint32_t structure_table_address
;
1470 uint16_t number_of_structures
;
1471 uint8_t smbios_bcd_revision
;
1472 } __attribute__((__packed__
));
1474 /* This goes at the beginning of every SMBIOS structure. */
1475 struct smbios_structure_header
{
1479 } __attribute__((__packed__
));
1481 /* SMBIOS type 0 - BIOS Information */
1482 struct smbios_type_0
{
1483 struct smbios_structure_header header
;
1485 uint8_t bios_version_str
;
1486 uint16_t bios_starting_address_segment
;
1487 uint8_t bios_release_date_str
;
1488 uint8_t bios_rom_size
;
1489 uint8_t bios_characteristics
[8];
1490 uint8_t bios_characteristics_extension_bytes
[2];
1491 uint8_t system_bios_major_release
;
1492 uint8_t system_bios_minor_release
;
1493 uint8_t embedded_controller_major_release
;
1494 uint8_t embedded_controller_minor_release
;
1495 } __attribute__((__packed__
));
1497 /* SMBIOS type 1 - System Information */
1498 struct smbios_type_1
{
1499 struct smbios_structure_header header
;
1500 uint8_t manufacturer_str
;
1501 uint8_t product_name_str
;
1502 uint8_t version_str
;
1503 uint8_t serial_number_str
;
1505 uint8_t wake_up_type
;
1506 uint8_t sku_number_str
;
1508 } __attribute__((__packed__
));
1510 /* SMBIOS type 3 - System Enclosure (v2.3) */
1511 struct smbios_type_3
{
1512 struct smbios_structure_header header
;
1513 uint8_t manufacturer_str
;
1515 uint8_t version_str
;
1516 uint8_t serial_number_str
;
1517 uint8_t asset_tag_number_str
;
1518 uint8_t boot_up_state
;
1519 uint8_t power_supply_state
;
1520 uint8_t thermal_state
;
1521 uint8_t security_status
;
1522 uint32_t oem_defined
;
1524 uint8_t number_of_power_cords
;
1525 uint8_t contained_element_count
;
1526 // contained elements follow
1527 } __attribute__((__packed__
));
1529 /* SMBIOS type 4 - Processor Information (v2.0) */
1530 struct smbios_type_4
{
1531 struct smbios_structure_header header
;
1532 uint8_t socket_designation_str
;
1533 uint8_t processor_type
;
1534 uint8_t processor_family
;
1535 uint8_t processor_manufacturer_str
;
1536 uint32_t processor_id
[2];
1537 uint8_t processor_version_str
;
1539 uint16_t external_clock
;
1541 uint16_t current_speed
;
1543 uint8_t processor_upgrade
;
1544 } __attribute__((__packed__
));
1546 /* SMBIOS type 16 - Physical Memory Array
1547 * Associated with one type 17 (Memory Device).
1549 struct smbios_type_16
{
1550 struct smbios_structure_header header
;
1553 uint8_t error_correction
;
1554 uint32_t maximum_capacity
;
1555 uint16_t memory_error_information_handle
;
1556 uint16_t number_of_memory_devices
;
1557 } __attribute__((__packed__
));
1559 /* SMBIOS type 17 - Memory Device
1560 * Associated with one type 19
1562 struct smbios_type_17
{
1563 struct smbios_structure_header header
;
1564 uint16_t physical_memory_array_handle
;
1565 uint16_t memory_error_information_handle
;
1566 uint16_t total_width
;
1567 uint16_t data_width
;
1569 uint8_t form_factor
;
1571 uint8_t device_locator_str
;
1572 uint8_t bank_locator_str
;
1573 uint8_t memory_type
;
1574 uint16_t type_detail
;
1575 } __attribute__((__packed__
));
1577 /* SMBIOS type 19 - Memory Array Mapped Address */
1578 struct smbios_type_19
{
1579 struct smbios_structure_header header
;
1580 uint32_t starting_address
;
1581 uint32_t ending_address
;
1582 uint16_t memory_array_handle
;
1583 uint8_t partition_width
;
1584 } __attribute__((__packed__
));
1586 /* SMBIOS type 20 - Memory Device Mapped Address */
1587 struct smbios_type_20
{
1588 struct smbios_structure_header header
;
1589 uint32_t starting_address
;
1590 uint32_t ending_address
;
1591 uint16_t memory_device_handle
;
1592 uint16_t memory_array_mapped_address_handle
;
1593 uint8_t partition_row_position
;
1594 uint8_t interleave_position
;
1595 uint8_t interleaved_data_depth
;
1596 } __attribute__((__packed__
));
1598 /* SMBIOS type 32 - System Boot Information */
1599 struct smbios_type_32
{
1600 struct smbios_structure_header header
;
1601 uint8_t reserved
[6];
1602 uint8_t boot_status
;
1603 } __attribute__((__packed__
));
1605 /* SMBIOS type 127 -- End-of-table */
1606 struct smbios_type_127
{
1607 struct smbios_structure_header header
;
1608 } __attribute__((__packed__
));
1611 smbios_entry_point_init(void *start
,
1612 uint16_t max_structure_size
,
1613 uint16_t structure_table_length
,
1614 uint32_t structure_table_address
,
1615 uint16_t number_of_structures
)
1619 struct smbios_entry_point
*ep
= (struct smbios_entry_point
*)start
;
1621 memcpy(ep
->anchor_string
, "_SM_", 4);
1623 ep
->smbios_major_version
= 2;
1624 ep
->smbios_minor_version
= 4;
1625 ep
->max_structure_size
= max_structure_size
;
1626 ep
->entry_point_revision
= 0;
1627 memset(ep
->formatted_area
, 0, 5);
1628 memcpy(ep
->intermediate_anchor_string
, "_DMI_", 5);
1630 ep
->structure_table_length
= structure_table_length
;
1631 ep
->structure_table_address
= structure_table_address
;
1632 ep
->number_of_structures
= number_of_structures
;
1633 ep
->smbios_bcd_revision
= 0x24;
1636 ep
->intermediate_checksum
= 0;
1639 for (i
= 0; i
< 0x10; i
++)
1640 sum
+= ((int8_t *)start
)[i
];
1641 ep
->checksum
= -sum
;
1644 for (i
= 0x10; i
< ep
->length
; i
++)
1645 sum
+= ((int8_t *)start
)[i
];
1646 ep
->intermediate_checksum
= -sum
;
1649 /* Type 0 -- BIOS Information */
1650 #define RELEASE_DATE_STR "01/01/2007"
1652 smbios_type_0_init(void *start
)
1654 struct smbios_type_0
*p
= (struct smbios_type_0
*)start
;
1657 p
->header
.length
= sizeof(struct smbios_type_0
);
1658 p
->header
.handle
= 0;
1661 p
->bios_version_str
= 1;
1662 p
->bios_starting_address_segment
= 0xe800;
1663 p
->bios_release_date_str
= 2;
1664 p
->bios_rom_size
= 0; /* FIXME */
1666 memset(p
->bios_characteristics
, 0, 7);
1667 p
->bios_characteristics
[7] = 0x08; /* BIOS characteristics not supported */
1668 p
->bios_characteristics_extension_bytes
[0] = 0;
1669 p
->bios_characteristics_extension_bytes
[1] = 0;
1671 p
->system_bios_major_release
= 1;
1672 p
->system_bios_minor_release
= 0;
1673 p
->embedded_controller_major_release
= 0xff;
1674 p
->embedded_controller_minor_release
= 0xff;
1676 start
+= sizeof(struct smbios_type_0
);
1677 memcpy((char *)start
, BX_APPNAME
, sizeof(BX_APPNAME
));
1678 start
+= sizeof(BX_APPNAME
);
1679 memcpy((char *)start
, RELEASE_DATE_STR
, sizeof(RELEASE_DATE_STR
));
1680 start
+= sizeof(RELEASE_DATE_STR
);
1681 *((uint8_t *)start
) = 0;
1686 /* Type 1 -- System Information */
1688 smbios_type_1_init(void *start
)
1690 struct smbios_type_1
*p
= (struct smbios_type_1
*)start
;
1692 p
->header
.length
= sizeof(struct smbios_type_1
);
1693 p
->header
.handle
= 0x100;
1695 p
->manufacturer_str
= 0;
1696 p
->product_name_str
= 0;
1698 p
->serial_number_str
= 0;
1700 memcpy(p
->uuid
, bios_uuid
, 16);
1702 p
->wake_up_type
= 0x06; /* power switch */
1703 p
->sku_number_str
= 0;
1706 start
+= sizeof(struct smbios_type_1
);
1707 *((uint16_t *)start
) = 0;
1712 /* Type 3 -- System Enclosure */
1714 smbios_type_3_init(void *start
)
1716 struct smbios_type_3
*p
= (struct smbios_type_3
*)start
;
1719 p
->header
.length
= sizeof(struct smbios_type_3
);
1720 p
->header
.handle
= 0x300;
1722 p
->manufacturer_str
= 0;
1723 p
->type
= 0x01; /* other */
1725 p
->serial_number_str
= 0;
1726 p
->asset_tag_number_str
= 0;
1727 p
->boot_up_state
= 0x03; /* safe */
1728 p
->power_supply_state
= 0x03; /* safe */
1729 p
->thermal_state
= 0x03; /* safe */
1730 p
->security_status
= 0x02; /* unknown */
1733 p
->number_of_power_cords
= 0;
1734 p
->contained_element_count
= 0;
1736 start
+= sizeof(struct smbios_type_3
);
1737 *((uint16_t *)start
) = 0;
1742 /* Type 4 -- Processor Information */
1744 smbios_type_4_init(void *start
, unsigned int cpu_number
)
1746 struct smbios_type_4
*p
= (struct smbios_type_4
*)start
;
1749 p
->header
.length
= sizeof(struct smbios_type_4
);
1750 p
->header
.handle
= 0x400 + cpu_number
;
1752 p
->socket_designation_str
= 1;
1753 p
->processor_type
= 0x03; /* CPU */
1754 p
->processor_family
= 0x01; /* other */
1755 p
->processor_manufacturer_str
= 0;
1757 p
->processor_id
[0] = cpuid_signature
;
1758 p
->processor_id
[1] = cpuid_features
;
1760 p
->processor_version_str
= 0;
1762 p
->external_clock
= 0;
1764 p
->max_speed
= 0; /* unknown */
1765 p
->current_speed
= 0; /* unknown */
1767 p
->status
= 0x41; /* socket populated, CPU enabled */
1768 p
->processor_upgrade
= 0x01; /* other */
1770 start
+= sizeof(struct smbios_type_4
);
1772 memcpy((char *)start
, "CPU " "\0" "" "\0" "", 7);
1773 ((char *)start
)[4] = cpu_number
+ '0';
1778 /* Type 16 -- Physical Memory Array */
1780 smbios_type_16_init(void *start
, uint32_t memsize
)
1782 struct smbios_type_16
*p
= (struct smbios_type_16
*)start
;
1784 p
->header
.type
= 16;
1785 p
->header
.length
= sizeof(struct smbios_type_16
);
1786 p
->header
.handle
= 0x1000;
1788 p
->location
= 0x01; /* other */
1789 p
->use
= 0x03; /* system memory */
1790 p
->error_correction
= 0x01; /* other */
1791 p
->maximum_capacity
= memsize
* 1024;
1792 p
->memory_error_information_handle
= 0xfffe; /* none provided */
1793 p
->number_of_memory_devices
= 1;
1795 start
+= sizeof(struct smbios_type_16
);
1796 *((uint16_t *)start
) = 0;
1801 /* Type 17 -- Memory Device */
1803 smbios_type_17_init(void *start
, uint32_t memory_size_mb
)
1805 struct smbios_type_17
*p
= (struct smbios_type_17
*)start
;
1807 p
->header
.type
= 17;
1808 p
->header
.length
= sizeof(struct smbios_type_17
);
1809 p
->header
.handle
= 0x1100;
1811 p
->physical_memory_array_handle
= 0x1000;
1812 p
->total_width
= 64;
1814 /* truncate memory_size_mb to 16 bits and clear most significant
1815 bit [indicates size in MB] */
1816 p
->size
= (uint16_t) memory_size_mb
& 0x7fff;
1817 p
->form_factor
= 0x09; /* DIMM */
1819 p
->device_locator_str
= 1;
1820 p
->bank_locator_str
= 0;
1821 p
->memory_type
= 0x07; /* RAM */
1824 start
+= sizeof(struct smbios_type_17
);
1825 memcpy((char *)start
, "DIMM 1", 7);
1827 *((uint8_t *)start
) = 0;
1832 /* Type 19 -- Memory Array Mapped Address */
1834 smbios_type_19_init(void *start
, uint32_t memory_size_mb
)
1836 struct smbios_type_19
*p
= (struct smbios_type_19
*)start
;
1838 p
->header
.type
= 19;
1839 p
->header
.length
= sizeof(struct smbios_type_19
);
1840 p
->header
.handle
= 0x1300;
1842 p
->starting_address
= 0;
1843 p
->ending_address
= (memory_size_mb
-1) * 1024;
1844 p
->memory_array_handle
= 0x1000;
1845 p
->partition_width
= 1;
1847 start
+= sizeof(struct smbios_type_19
);
1848 *((uint16_t *)start
) = 0;
1853 /* Type 20 -- Memory Device Mapped Address */
1855 smbios_type_20_init(void *start
, uint32_t memory_size_mb
)
1857 struct smbios_type_20
*p
= (struct smbios_type_20
*)start
;
1859 p
->header
.type
= 20;
1860 p
->header
.length
= sizeof(struct smbios_type_20
);
1861 p
->header
.handle
= 0x1400;
1863 p
->starting_address
= 0;
1864 p
->ending_address
= (memory_size_mb
-1)*1024;
1865 p
->memory_device_handle
= 0x1100;
1866 p
->memory_array_mapped_address_handle
= 0x1300;
1867 p
->partition_row_position
= 1;
1868 p
->interleave_position
= 0;
1869 p
->interleaved_data_depth
= 0;
1871 start
+= sizeof(struct smbios_type_20
);
1873 *((uint16_t *)start
) = 0;
1877 /* Type 32 -- System Boot Information */
1879 smbios_type_32_init(void *start
)
1881 struct smbios_type_32
*p
= (struct smbios_type_32
*)start
;
1883 p
->header
.type
= 32;
1884 p
->header
.length
= sizeof(struct smbios_type_32
);
1885 p
->header
.handle
= 0x2000;
1886 memset(p
->reserved
, 0, 6);
1887 p
->boot_status
= 0; /* no errors detected */
1889 start
+= sizeof(struct smbios_type_32
);
1890 *((uint16_t *)start
) = 0;
1895 /* Type 127 -- End of Table */
1897 smbios_type_127_init(void *start
)
1899 struct smbios_type_127
*p
= (struct smbios_type_127
*)start
;
1901 p
->header
.type
= 127;
1902 p
->header
.length
= sizeof(struct smbios_type_127
);
1903 p
->header
.handle
= 0x7f00;
1905 start
+= sizeof(struct smbios_type_127
);
1906 *((uint16_t *)start
) = 0;
1911 void smbios_init(void)
1913 unsigned cpu_num
, nr_structs
= 0, max_struct_size
= 0;
1914 char *start
, *p
, *q
;
1915 int memsize
= ram_size
/ (1024 * 1024);
1917 #ifdef BX_USE_EBDA_TABLES
1918 ebda_cur_addr
= align(ebda_cur_addr
, 16);
1919 start
= (void *)(ebda_cur_addr
);
1921 bios_table_cur_addr
= align(bios_table_cur_addr
, 16);
1922 start
= (void *)(bios_table_cur_addr
);
1925 p
= (char *)start
+ sizeof(struct smbios_entry_point
);
1927 #define add_struct(fn) { \
1930 if ((q - p) > max_struct_size) \
1931 max_struct_size = q - p; \
1935 add_struct(smbios_type_0_init(p
));
1936 add_struct(smbios_type_1_init(p
));
1937 add_struct(smbios_type_3_init(p
));
1938 for (cpu_num
= 1; cpu_num
<= smp_cpus
; cpu_num
++)
1939 add_struct(smbios_type_4_init(p
, cpu_num
));
1940 add_struct(smbios_type_16_init(p
, memsize
));
1941 add_struct(smbios_type_17_init(p
, memsize
));
1942 add_struct(smbios_type_19_init(p
, memsize
));
1943 add_struct(smbios_type_20_init(p
, memsize
));
1944 add_struct(smbios_type_32_init(p
));
1945 add_struct(smbios_type_127_init(p
));
1949 smbios_entry_point_init(
1950 start
, max_struct_size
,
1951 (p
- (char *)start
) - sizeof(struct smbios_entry_point
),
1952 (uint32_t)(start
+ sizeof(struct smbios_entry_point
)),
1955 #ifdef BX_USE_EBDA_TABLES
1956 ebda_cur_addr
+= (p
- (char *)start
);
1958 bios_table_cur_addr
+= (p
- (char *)start
);
1961 BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start
);
1964 void rombios32_init(void)
1966 BX_INFO("Starting rombios32\n");
1978 if (bios_table_cur_addr
!= 0) {
1987 bios_lock_shadow_ram();
1989 BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr
);
1990 if (bios_table_cur_addr
> bios_table_end_addr
)
1991 BX_PANIC("bios_table_end_addr overflow!\n");