- clear out RSDT memory on init (patch by Bernhard Kauer from the ML)
[gplbios.git] / rombios32.c
blob09b66661827951e2f35eac836c410bddb342e92b
1 /////////////////////////////////////////////////////////////////////////
2 // $Id$
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // 32 bit Bochs BIOS init code
6 // Copyright (C) 2006 Fabrice Bellard
7 //
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
21 #include <stdarg.h>
22 #include <stddef.h>
24 #include "rombios.h"
26 typedef signed char int8_t;
27 typedef short int16_t;
28 typedef int int32_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 */
41 #define BX_USE_SMM
43 #define cpuid(index, eax, ebx, ecx, edx) \
44 asm volatile ("cpuid" \
45 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
46 : "0" (index))
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
55 #define APIC_ID 0x020
56 #define APIC_LVT3 0x370
58 #define APIC_ENABLED 0x0100
60 #define AP_BOOT_ADDR 0x10000
62 #define MPTABLE_MAX_SIZE 0x00002000
63 #define SMI_CMD_IO_ADDR 0xb2
65 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
67 static inline void outl(int addr, int val)
69 asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val));
72 static inline void outw(int addr, int val)
74 asm volatile ("outw %w1, %w0" : : "d" (addr), "a" (val));
77 static inline void outb(int addr, int val)
79 asm volatile ("outb %b1, %w0" : : "d" (addr), "a" (val));
82 static inline uint32_t inl(int addr)
84 uint32_t val;
85 asm volatile ("inl %w1, %0" : "=a" (val) : "d" (addr));
86 return val;
89 static inline uint16_t inw(int addr)
91 uint16_t val;
92 asm volatile ("inw %w1, %w0" : "=a" (val) : "d" (addr));
93 return val;
96 static inline uint8_t inb(int addr)
98 uint8_t val;
99 asm volatile ("inb %w1, %b0" : "=a" (val) : "d" (addr));
100 return val;
103 static inline void writel(void *addr, uint32_t val)
105 *(volatile uint32_t *)addr = val;
108 static inline void writew(void *addr, uint16_t val)
110 *(volatile uint16_t *)addr = val;
113 static inline void writeb(void *addr, uint8_t val)
115 *(volatile uint8_t *)addr = val;
118 static inline uint32_t readl(const void *addr)
120 return *(volatile const uint32_t *)addr;
123 static inline uint16_t readw(const void *addr)
125 return *(volatile const uint16_t *)addr;
128 static inline uint8_t readb(const void *addr)
130 return *(volatile const uint8_t *)addr;
133 static inline void putc(int c)
135 outb(INFO_PORT, c);
138 static inline int isdigit(int c)
140 return c >= '0' && c <= '9';
143 void *memset(void *d1, int val, size_t len)
145 uint8_t *d = d1;
147 while (len--) {
148 *d++ = val;
150 return d1;
153 void *memcpy(void *d1, const void *s1, size_t len)
155 uint8_t *d = d1;
156 const uint8_t *s = s1;
158 while (len--) {
159 *d++ = *s++;
161 return d1;
164 void *memmove(void *d1, const void *s1, size_t len)
166 uint8_t *d = d1;
167 const uint8_t *s = s1;
169 if (d <= s) {
170 while (len--) {
171 *d++ = *s++;
173 } else {
174 d += len;
175 s += len;
176 while (len--) {
177 *--d = *--s;
180 return d1;
183 size_t strlen(const char *s)
185 const char *s1;
186 for(s1 = s; *s1 != '\0'; s1++);
187 return s1 - s;
190 /* from BSD ppp sources */
191 int vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
193 int c, i, n;
194 int width, prec, fillch;
195 int base, len, neg;
196 unsigned long val = 0;
197 const char *f;
198 char *str, *buf0;
199 char num[32];
200 static const char hexchars[] = "0123456789abcdef";
202 buf0 = buf;
203 --buflen;
204 while (buflen > 0) {
205 for (f = fmt; *f != '%' && *f != 0; ++f)
207 if (f > fmt) {
208 len = f - fmt;
209 if (len > buflen)
210 len = buflen;
211 memcpy(buf, fmt, len);
212 buf += len;
213 buflen -= len;
214 fmt = f;
216 if (*fmt == 0)
217 break;
218 c = *++fmt;
219 width = prec = 0;
220 fillch = ' ';
221 if (c == '0') {
222 fillch = '0';
223 c = *++fmt;
225 if (c == '*') {
226 width = va_arg(args, int);
227 c = *++fmt;
228 } else {
229 while (isdigit(c)) {
230 width = width * 10 + c - '0';
231 c = *++fmt;
234 if (c == '.') {
235 c = *++fmt;
236 if (c == '*') {
237 prec = va_arg(args, int);
238 c = *++fmt;
239 } else {
240 while (isdigit(c)) {
241 prec = prec * 10 + c - '0';
242 c = *++fmt;
246 /* modifiers */
247 switch(c) {
248 case 'l':
249 c = *++fmt;
250 break;
251 default:
252 break;
254 str = 0;
255 base = 0;
256 neg = 0;
257 ++fmt;
258 switch (c) {
259 case 'd':
260 i = va_arg(args, int);
261 if (i < 0) {
262 neg = 1;
263 val = -i;
264 } else
265 val = i;
266 base = 10;
267 break;
268 case 'o':
269 val = va_arg(args, unsigned int);
270 base = 8;
271 break;
272 case 'x':
273 case 'X':
274 val = va_arg(args, unsigned int);
275 base = 16;
276 break;
277 case 'p':
278 val = (unsigned long) va_arg(args, void *);
279 base = 16;
280 neg = 2;
281 break;
282 case 's':
283 str = va_arg(args, char *);
284 break;
285 case 'c':
286 num[0] = va_arg(args, int);
287 num[1] = 0;
288 str = num;
289 break;
290 default:
291 *buf++ = '%';
292 if (c != '%')
293 --fmt; /* so %z outputs %z etc. */
294 --buflen;
295 continue;
297 if (base != 0) {
298 str = num + sizeof(num);
299 *--str = 0;
300 while (str > num + neg) {
301 *--str = hexchars[val % base];
302 val = val / base;
303 if (--prec <= 0 && val == 0)
304 break;
306 switch (neg) {
307 case 1:
308 *--str = '-';
309 break;
310 case 2:
311 *--str = 'x';
312 *--str = '0';
313 break;
315 len = num + sizeof(num) - 1 - str;
316 } else {
317 len = strlen(str);
318 if (prec > 0 && len > prec)
319 len = prec;
321 if (width > 0) {
322 if (width > buflen)
323 width = buflen;
324 if ((n = width - len) > 0) {
325 buflen -= n;
326 for (; n > 0; --n)
327 *buf++ = fillch;
330 if (len > buflen)
331 len = buflen;
332 memcpy(buf, str, len);
333 buf += len;
334 buflen -= len;
336 *buf = 0;
337 return buf - buf0;
340 void bios_printf(int flags, const char *fmt, ...)
342 va_list ap;
343 char buf[1024];
344 const char *s;
346 va_start(ap, fmt);
347 vsnprintf(buf, sizeof(buf), fmt, ap);
348 s = buf;
349 while (*s)
350 putc(*s++);
351 va_end(ap);
354 void delay_ms(int n)
356 int i, j;
357 for(i = 0; i < n; i++) {
358 #ifdef BX_QEMU
359 /* approximative ! */
360 for(j = 0; j < 1000000; j++);
361 #else
363 int r1, r2;
364 j = 66;
365 r1 = inb(0x61) & 0x10;
366 do {
367 r2 = inb(0x61) & 0x10;
368 if (r1 != r2) {
369 j--;
370 r1 = r2;
372 } while (j > 0);
374 #endif
378 int smp_cpus;
379 uint32_t cpuid_features;
380 uint32_t cpuid_ext_features;
381 unsigned long ram_size;
382 #ifdef BX_USE_EBDA_TABLES
383 unsigned long ebda_cur_addr;
384 #endif
385 int acpi_enabled;
386 uint32_t pm_io_base, smb_io_base;
387 int pm_sci_int;
388 unsigned long bios_table_cur_addr;
389 unsigned long bios_table_end_addr;
391 void cpu_probe(void)
393 uint32_t eax, ebx, ecx, edx;
394 cpuid(1, eax, ebx, ecx, edx);
395 cpuid_features = edx;
396 cpuid_ext_features = ecx;
399 static int cmos_readb(int addr)
401 outb(0x70, addr);
402 return inb(0x71);
405 void ram_probe(void)
407 ram_size = (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
408 16 * 1024 * 1024;
409 #ifdef BX_USE_EBDA_TABLES
410 ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
411 #endif
412 BX_INFO("ram_size=0x%08lx\n");
415 /****************************************************/
416 /* SMP probe */
418 extern uint8_t smp_ap_boot_code_start;
419 extern uint8_t smp_ap_boot_code_end;
421 /* find the number of CPUs by launching a SIPI to them */
422 void smp_probe(void)
424 uint32_t val, sipi_vector;
426 smp_cpus = 1;
427 if (cpuid_features & CPUID_APIC) {
429 /* enable local APIC */
430 val = readl(APIC_BASE + APIC_SVR);
431 val |= APIC_ENABLED;
432 writel(APIC_BASE + APIC_SVR, val);
434 writew((void *)CPU_COUNT_ADDR, 1);
435 /* copy AP boot code */
436 memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start,
437 &smp_ap_boot_code_end - &smp_ap_boot_code_start);
439 /* broadcast SIPI */
440 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500);
441 sipi_vector = AP_BOOT_ADDR >> 12;
442 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector);
444 delay_ms(10);
446 smp_cpus = readw((void *)CPU_COUNT_ADDR);
448 BX_INFO("Found %d cpu(s)\n", smp_cpus);
451 /****************************************************/
452 /* PCI init */
454 #define PCI_ADDRESS_SPACE_MEM 0x00
455 #define PCI_ADDRESS_SPACE_IO 0x01
456 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
458 #define PCI_ROM_SLOT 6
459 #define PCI_NUM_REGIONS 7
461 #define PCI_DEVICES_MAX 64
463 #define PCI_VENDOR_ID 0x00 /* 16 bits */
464 #define PCI_DEVICE_ID 0x02 /* 16 bits */
465 #define PCI_COMMAND 0x04 /* 16 bits */
466 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
467 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
468 #define PCI_CLASS_DEVICE 0x0a /* Device class */
469 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
470 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
471 #define PCI_MIN_GNT 0x3e /* 8 bits */
472 #define PCI_MAX_LAT 0x3f /* 8 bits */
474 typedef struct PCIDevice {
475 int bus;
476 int devfn;
477 } PCIDevice;
479 static uint32_t pci_bios_io_addr;
480 static uint32_t pci_bios_mem_addr;
481 static uint32_t pci_bios_bigmem_addr;
482 /* host irqs corresponding to PCI irqs A-D */
483 static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
484 static PCIDevice i440_pcidev;
486 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
488 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
489 outl(0xcfc, val);
492 static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
494 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
495 outw(0xcfc + (addr & 2), val);
498 static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
500 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
501 outb(0xcfc + (addr & 3), val);
504 static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
506 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
507 return inl(0xcfc);
510 static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
512 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
513 return inw(0xcfc + (addr & 2));
516 static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
518 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
519 return inb(0xcfc + (addr & 3));
522 static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
524 uint16_t cmd;
525 uint32_t ofs, old_addr;
527 if ( region_num == PCI_ROM_SLOT ) {
528 ofs = 0x30;
529 }else{
530 ofs = 0x10 + region_num * 4;
533 old_addr = pci_config_readl(d, ofs);
535 pci_config_writel(d, ofs, addr);
536 BX_INFO("region %d: 0x%08x\n", region_num, addr);
538 /* enable memory mappings */
539 cmd = pci_config_readw(d, PCI_COMMAND);
540 if ( region_num == PCI_ROM_SLOT )
541 cmd |= 2;
542 else if (old_addr & PCI_ADDRESS_SPACE_IO)
543 cmd |= 1;
544 else
545 cmd |= 2;
546 pci_config_writew(d, PCI_COMMAND, cmd);
549 /* return the global irq number corresponding to a given device irq
550 pin. We could also use the bus number to have a more precise
551 mapping. */
552 static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
554 int slot_addend;
555 slot_addend = (pci_dev->devfn >> 3) - 1;
556 return (irq_num + slot_addend) & 3;
559 static int find_bios_table_area(void)
561 unsigned long addr;
562 for(addr = 0xf0000; addr < 0x100000; addr += 16) {
563 if (*(uint32_t *)addr == 0xaafb4442) {
564 bios_table_cur_addr = addr + 8;
565 bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4);
566 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
567 bios_table_cur_addr, bios_table_end_addr);
568 return 0;
571 return -1;
574 static void bios_shadow_init(PCIDevice *d)
576 int v;
578 if (find_bios_table_area() < 0)
579 return;
581 /* remap the BIOS to shadow RAM an keep it read/write while we
582 are writing tables */
583 memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
584 v = pci_config_readb(d, 0x59);
585 v = (v & 0x0f) | (0x30);
586 pci_config_writeb(d, 0x59, v);
587 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
589 i440_pcidev = *d;
592 static void bios_lock_shadow_ram(void)
594 PCIDevice *d = &i440_pcidev;
595 int v;
597 wbinvd();
598 v = pci_config_readb(d, 0x59);
599 v = (v & 0x0f) | (0x10);
600 pci_config_writeb(d, 0x59, v);
603 static void pci_bios_init_bridges(PCIDevice *d)
605 uint16_t vendor_id, device_id;
607 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
608 device_id = pci_config_readw(d, PCI_DEVICE_ID);
610 if (vendor_id == 0x8086 && device_id == 0x7000) {
611 int i, irq;
612 uint8_t elcr[2];
614 /* PIIX3 bridge */
616 elcr[0] = 0x00;
617 elcr[1] = 0x00;
618 for(i = 0; i < 4; i++) {
619 irq = pci_irqs[i];
620 /* set to trigger level */
621 elcr[irq >> 3] |= (1 << (irq & 7));
622 /* activate irq remapping in PIIX */
623 pci_config_writeb(d, 0x60 + i, irq);
625 outb(0x4d0, elcr[0]);
626 outb(0x4d1, elcr[1]);
627 BX_INFO("PIIX3 init: elcr=%02x %02x\n",
628 elcr[0], elcr[1]);
629 } else if (vendor_id == 0x8086 && device_id == 0x1237) {
630 /* i440 PCI bridge */
631 bios_shadow_init(d);
635 extern uint8_t smm_relocation_start, smm_relocation_end;
636 extern uint8_t smm_code_start, smm_code_end;
638 #ifdef BX_USE_SMM
639 static void smm_init(PCIDevice *d)
641 /* copy the SMM relocation code */
642 memcpy((void *)0x38000, &smm_relocation_start,
643 &smm_relocation_end - &smm_relocation_start);
645 /* enable SMI generation when writing to the APMC register */
646 pci_config_writel(d, 0x58, pci_config_readl(d, 0x58) | (1 << 25));
648 /* init APM status port */
649 outb(0xb3, 0x01);
651 /* raise an SMI interrupt */
652 outb(0xb2, 0x00);
654 /* wait until SMM code executed */
655 while (inb(0xb3) != 0x00);
657 /* enable the SMM memory window */
658 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
660 /* copy the SMM code */
661 memcpy((void *)0xa8000, &smm_code_start,
662 &smm_code_end - &smm_code_start);
663 wbinvd();
665 /* close the SMM memory window and enable normal SMM */
666 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
668 #endif
670 static void pci_bios_init_device(PCIDevice *d)
672 int class;
673 uint32_t *paddr;
674 int i, pin, pic_irq, vendor_id, device_id;
676 class = pci_config_readw(d, PCI_CLASS_DEVICE);
677 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
678 device_id = pci_config_readw(d, PCI_DEVICE_ID);
679 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
680 d->bus, d->devfn, vendor_id, device_id);
681 switch(class) {
682 case 0x0101:
683 if (vendor_id == 0x8086 && device_id == 0x7010) {
684 /* PIIX3 IDE */
685 pci_config_writew(d, 0x40, 0x8000); // enable IDE0
686 pci_config_writew(d, 0x42, 0x8000); // enable IDE1
687 goto default_map;
688 } else {
689 /* IDE: we map it as in ISA mode */
690 pci_set_io_region_addr(d, 0, 0x1f0);
691 pci_set_io_region_addr(d, 1, 0x3f4);
692 pci_set_io_region_addr(d, 2, 0x170);
693 pci_set_io_region_addr(d, 3, 0x374);
695 break;
696 case 0x0300:
697 if (vendor_id != 0x1234)
698 goto default_map;
699 /* VGA: map frame buffer to default Bochs VBE address */
700 pci_set_io_region_addr(d, 0, 0xE0000000);
701 break;
702 case 0x0800:
703 /* PIC */
704 if (vendor_id == 0x1014) {
705 /* IBM */
706 if (device_id == 0x0046 || device_id == 0xFFFF) {
707 /* MPIC & MPIC2 */
708 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
711 break;
712 case 0xff00:
713 if (vendor_id == 0x0106b &&
714 (device_id == 0x0017 || device_id == 0x0022)) {
715 /* macio bridge */
716 pci_set_io_region_addr(d, 0, 0x80800000);
718 break;
719 default:
720 default_map:
721 /* default memory mappings */
722 for(i = 0; i < PCI_NUM_REGIONS; i++) {
723 int ofs;
724 uint32_t val, size ;
726 if (i == PCI_ROM_SLOT)
727 ofs = 0x30;
728 else
729 ofs = 0x10 + i * 4;
730 pci_config_writel(d, ofs, 0xffffffff);
731 val = pci_config_readl(d, ofs);
732 if (val != 0) {
733 size = (~(val & ~0xf)) + 1;
734 if (val & PCI_ADDRESS_SPACE_IO)
735 paddr = &pci_bios_io_addr;
736 else if (size >= 0x04000000)
737 paddr = &pci_bios_bigmem_addr;
738 else
739 paddr = &pci_bios_mem_addr;
740 *paddr = (*paddr + size - 1) & ~(size - 1);
741 pci_set_io_region_addr(d, i, *paddr);
742 *paddr += size;
745 break;
748 /* map the interrupt */
749 pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
750 if (pin != 0) {
751 pin = pci_slot_get_pirq(d, pin - 1);
752 pic_irq = pci_irqs[pin];
753 pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
756 if (vendor_id == 0x8086 && device_id == 0x7113) {
757 /* PIIX4 Power Management device (for ACPI) */
758 pm_io_base = PM_IO_BASE;
759 pci_config_writel(d, 0x40, pm_io_base | 1);
760 pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
761 smb_io_base = SMB_IO_BASE;
762 pci_config_writel(d, 0x90, smb_io_base | 1);
763 pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
764 pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE);
765 #ifdef BX_USE_SMM
766 smm_init(d);
767 #endif
768 acpi_enabled = 1;
772 void pci_for_each_device(void (*init_func)(PCIDevice *d))
774 PCIDevice d1, *d = &d1;
775 int bus, devfn;
776 uint16_t vendor_id, device_id;
778 for(bus = 0; bus < 1; bus++) {
779 for(devfn = 0; devfn < 256; devfn++) {
780 d->bus = bus;
781 d->devfn = devfn;
782 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
783 device_id = pci_config_readw(d, PCI_DEVICE_ID);
784 if (vendor_id != 0xffff || device_id != 0xffff) {
785 init_func(d);
791 void pci_bios_init(void)
793 pci_bios_io_addr = 0xc000;
794 pci_bios_mem_addr = 0xf0000000;
795 pci_bios_bigmem_addr = ram_size;
796 if (pci_bios_bigmem_addr < 0x90000000)
797 pci_bios_bigmem_addr = 0x90000000;
799 pci_for_each_device(pci_bios_init_bridges);
801 pci_for_each_device(pci_bios_init_device);
804 /****************************************************/
805 /* Multi Processor table init */
807 static void putb(uint8_t **pp, int val)
809 uint8_t *q;
810 q = *pp;
811 *q++ = val;
812 *pp = q;
815 static void putstr(uint8_t **pp, const char *str)
817 uint8_t *q;
818 q = *pp;
819 while (*str)
820 *q++ = *str++;
821 *pp = q;
824 static void putle16(uint8_t **pp, int val)
826 uint8_t *q;
827 q = *pp;
828 *q++ = val;
829 *q++ = val >> 8;
830 *pp = q;
833 static void putle32(uint8_t **pp, int val)
835 uint8_t *q;
836 q = *pp;
837 *q++ = val;
838 *q++ = val >> 8;
839 *q++ = val >> 16;
840 *q++ = val >> 24;
841 *pp = q;
844 static int mpf_checksum(const uint8_t *data, int len)
846 int sum, i;
847 sum = 0;
848 for(i = 0; i < len; i++)
849 sum += data[i];
850 return sum & 0xff;
853 static unsigned long align(unsigned long addr, unsigned long v)
855 return (addr + v - 1) & ~(v - 1);
858 static void mptable_init(void)
860 uint8_t *mp_config_table, *q, *float_pointer_struct;
861 int ioapic_id, i, len;
862 int mp_config_table_size;
864 #ifdef BX_USE_EBDA_TABLES
865 mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
866 #else
867 bios_table_cur_addr = align(bios_table_cur_addr, 16);
868 mp_config_table = (uint8_t *)bios_table_cur_addr;
869 #endif
870 q = mp_config_table;
871 putstr(&q, "PCMP"); /* "PCMP signature */
872 putle16(&q, 0); /* table length (patched later) */
873 putb(&q, 4); /* spec rev */
874 putb(&q, 0); /* checksum (patched later) */
875 #ifdef BX_QEMU
876 putstr(&q, "QEMUCPU "); /* OEM id */
877 #else
878 putstr(&q, "BOCHSCPU");
879 #endif
880 putstr(&q, "0.1 "); /* vendor id */
881 putle32(&q, 0); /* OEM table ptr */
882 putle16(&q, 0); /* OEM table size */
883 putle16(&q, smp_cpus + 18); /* entry count */
884 putle32(&q, 0xfee00000); /* local APIC addr */
885 putle16(&q, 0); /* ext table length */
886 putb(&q, 0); /* ext table checksum */
887 putb(&q, 0); /* reserved */
889 for(i = 0; i < smp_cpus; i++) {
890 putb(&q, 0); /* entry type = processor */
891 putb(&q, i); /* APIC id */
892 putb(&q, 0x11); /* local APIC version number */
893 if (i == 0)
894 putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
895 else
896 putb(&q, 1); /* cpu flags: enabled */
897 putb(&q, 0); /* cpu signature */
898 putb(&q, 6);
899 putb(&q, 0);
900 putb(&q, 0);
901 putle16(&q, 0x201); /* feature flags */
902 putle16(&q, 0);
904 putle16(&q, 0); /* reserved */
905 putle16(&q, 0);
906 putle16(&q, 0);
907 putle16(&q, 0);
910 /* isa bus */
911 putb(&q, 1); /* entry type = bus */
912 putb(&q, 0); /* bus ID */
913 putstr(&q, "ISA ");
915 /* ioapic */
916 ioapic_id = smp_cpus;
917 putb(&q, 2); /* entry type = I/O APIC */
918 putb(&q, ioapic_id); /* apic ID */
919 putb(&q, 0x11); /* I/O APIC version number */
920 putb(&q, 1); /* enable */
921 putle32(&q, 0xfec00000); /* I/O APIC addr */
923 /* irqs */
924 for(i = 0; i < 16; i++) {
925 putb(&q, 3); /* entry type = I/O interrupt */
926 putb(&q, 0); /* interrupt type = vectored interrupt */
927 putb(&q, 0); /* flags: po=0, el=0 */
928 putb(&q, 0);
929 putb(&q, 0); /* source bus ID = ISA */
930 putb(&q, i); /* source bus IRQ */
931 putb(&q, ioapic_id); /* dest I/O APIC ID */
932 putb(&q, i); /* dest I/O APIC interrupt in */
934 /* patch length */
935 len = q - mp_config_table;
936 mp_config_table[4] = len;
937 mp_config_table[5] = len >> 8;
939 mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
941 mp_config_table_size = q - mp_config_table;
943 #ifndef BX_USE_EBDA_TABLES
944 bios_table_cur_addr += mp_config_table_size;
945 #endif
947 /* floating pointer structure */
948 #ifdef BX_USE_EBDA_TABLES
949 ebda_cur_addr = align(ebda_cur_addr, 16);
950 float_pointer_struct = (uint8_t *)ebda_cur_addr;
951 #else
952 bios_table_cur_addr = align(bios_table_cur_addr, 16);
953 float_pointer_struct = (uint8_t *)bios_table_cur_addr;
954 #endif
955 q = float_pointer_struct;
956 putstr(&q, "_MP_");
957 /* pointer to MP config table */
958 putle32(&q, (unsigned long)mp_config_table);
960 putb(&q, 1); /* length in 16 byte units */
961 putb(&q, 4); /* MP spec revision */
962 putb(&q, 0); /* checksum (patched later) */
963 putb(&q, 0); /* MP feature byte 1 */
965 putb(&q, 0);
966 putb(&q, 0);
967 putb(&q, 0);
968 putb(&q, 0);
969 float_pointer_struct[10] =
970 -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
971 #ifdef BX_USE_EBDA_TABLES
972 ebda_cur_addr += (q - float_pointer_struct);
973 #else
974 bios_table_cur_addr += (q - float_pointer_struct);
975 #endif
976 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
977 (unsigned long)float_pointer_struct,
978 (unsigned long)mp_config_table,
979 mp_config_table_size);
982 /****************************************************/
983 /* ACPI tables init */
985 /* Table structure from Linux kernel (the ACPI tables are under the
986 BSD license) */
988 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
989 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
990 uint32_t length; /* Length of table, in bytes, including header */\
991 uint8_t revision; /* ACPI Specification minor version # */\
992 uint8_t checksum; /* To make sum of entire table == 0 */\
993 uint8_t oem_id [6]; /* OEM identification */\
994 uint8_t oem_table_id [8]; /* OEM table identification */\
995 uint32_t oem_revision; /* OEM revision number */\
996 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
997 uint32_t asl_compiler_revision; /* ASL compiler revision number */
1000 struct acpi_table_header /* ACPI common table header */
1002 ACPI_TABLE_HEADER_DEF
1005 struct rsdp_descriptor /* Root System Descriptor Pointer */
1007 uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */
1008 uint8_t checksum; /* To make sum of struct == 0 */
1009 uint8_t oem_id [6]; /* OEM identification */
1010 uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
1011 uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
1012 uint32_t length; /* XSDT Length in bytes including hdr */
1013 uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
1014 uint8_t extended_checksum; /* Checksum of entire table */
1015 uint8_t reserved [3]; /* Reserved field must be 0 */
1019 * ACPI 1.0 Root System Description Table (RSDT)
1021 struct rsdt_descriptor_rev1
1023 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
1024 uint32_t table_offset_entry [2]; /* Array of pointers to other */
1025 /* ACPI tables */
1029 * ACPI 1.0 Firmware ACPI Control Structure (FACS)
1031 struct facs_descriptor_rev1
1033 uint8_t signature[4]; /* ACPI Signature */
1034 uint32_t length; /* Length of structure, in bytes */
1035 uint32_t hardware_signature; /* Hardware configuration signature */
1036 uint32_t firmware_waking_vector; /* ACPI OS waking vector */
1037 uint32_t global_lock; /* Global Lock */
1038 uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */
1039 uint32_t reserved1 : 31; /* Must be 0 */
1040 uint8_t resverved3 [40]; /* Reserved - must be zero */
1045 * ACPI 1.0 Fixed ACPI Description Table (FADT)
1047 struct fadt_descriptor_rev1
1049 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
1050 uint32_t firmware_ctrl; /* Physical address of FACS */
1051 uint32_t dsdt; /* Physical address of DSDT */
1052 uint8_t model; /* System Interrupt Model */
1053 uint8_t reserved1; /* Reserved */
1054 uint16_t sci_int; /* System vector of SCI interrupt */
1055 uint32_t smi_cmd; /* Port address of SMI command port */
1056 uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
1057 uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
1058 uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
1059 uint8_t reserved2; /* Reserved - must be zero */
1060 uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
1061 uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
1062 uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
1063 uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
1064 uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
1065 uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
1066 uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
1067 uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
1068 uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
1069 uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
1070 uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
1071 uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
1072 uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
1073 uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
1074 uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
1075 uint8_t reserved3; /* Reserved */
1076 uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
1077 uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
1078 uint16_t flush_size; /* Size of area read to flush caches */
1079 uint16_t flush_stride; /* Stride used in flushing caches */
1080 uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
1081 uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
1082 uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
1083 uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
1084 uint8_t century; /* Index to century in RTC CMOS RAM */
1085 uint8_t reserved4; /* Reserved */
1086 uint8_t reserved4a; /* Reserved */
1087 uint8_t reserved4b; /* Reserved */
1088 #if 0
1089 uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
1090 uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
1091 uint32_t proc_c1 : 1; /* All processors support C1 state */
1092 uint32_t plvl2_up : 1; /* C2 state works on MP system */
1093 uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
1094 uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
1095 uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
1096 uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
1097 uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
1098 uint32_t reserved5 : 23; /* Reserved - must be zero */
1099 #else
1100 uint32_t flags;
1101 #endif
1105 * MADT values and structures
1108 /* Values for MADT PCATCompat */
1110 #define DUAL_PIC 0
1111 #define MULTIPLE_APIC 1
1114 /* Master MADT */
1116 struct multiple_apic_table
1118 ACPI_TABLE_HEADER_DEF /* ACPI common table header */
1119 uint32_t local_apic_address; /* Physical address of local APIC */
1120 #if 0
1121 uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
1122 uint32_t reserved1 : 31;
1123 #else
1124 uint32_t flags;
1125 #endif
1129 /* Values for Type in APIC_HEADER_DEF */
1131 #define APIC_PROCESSOR 0
1132 #define APIC_IO 1
1133 #define APIC_XRUPT_OVERRIDE 2
1134 #define APIC_NMI 3
1135 #define APIC_LOCAL_NMI 4
1136 #define APIC_ADDRESS_OVERRIDE 5
1137 #define APIC_IO_SAPIC 6
1138 #define APIC_LOCAL_SAPIC 7
1139 #define APIC_XRUPT_SOURCE 8
1140 #define APIC_RESERVED 9 /* 9 and greater are reserved */
1143 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
1145 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\
1146 uint8_t type; \
1147 uint8_t length;
1149 /* Sub-structures for MADT */
1151 struct madt_processor_apic
1153 APIC_HEADER_DEF
1154 uint8_t processor_id; /* ACPI processor id */
1155 uint8_t local_apic_id; /* Processor's local APIC id */
1156 #if 0
1157 uint32_t processor_enabled: 1; /* Processor is usable if set */
1158 uint32_t reserved2 : 31; /* Reserved, must be zero */
1159 #else
1160 uint32_t flags;
1161 #endif
1164 struct madt_io_apic
1166 APIC_HEADER_DEF
1167 uint8_t io_apic_id; /* I/O APIC ID */
1168 uint8_t reserved; /* Reserved - must be zero */
1169 uint32_t address; /* APIC physical address */
1170 uint32_t interrupt; /* Global system interrupt where INTI
1171 * lines start */
1174 #include "acpi-dsdt.hex"
1176 static inline uint16_t cpu_to_le16(uint16_t x)
1178 return x;
1181 static inline uint32_t cpu_to_le32(uint32_t x)
1183 return x;
1186 static int acpi_checksum(const uint8_t *data, int len)
1188 int sum, i;
1189 sum = 0;
1190 for(i = 0; i < len; i++)
1191 sum += data[i];
1192 return (-sum) & 0xff;
1195 static void acpi_build_table_header(struct acpi_table_header *h,
1196 char *sig, int len)
1198 memcpy(h->signature, sig, 4);
1199 h->length = cpu_to_le32(len);
1200 h->revision = 1;
1201 #ifdef BX_QEMU
1202 memcpy(h->oem_id, "QEMU ", 6);
1203 memcpy(h->oem_table_id, "QEMU", 4);
1204 #else
1205 memcpy(h->oem_id, "BOCHS ", 6);
1206 memcpy(h->oem_table_id, "BXPC", 4);
1207 #endif
1208 memcpy(h->oem_table_id + 4, sig, 4);
1209 h->oem_revision = cpu_to_le32(1);
1210 #ifdef BX_QEMU
1211 memcpy(h->asl_compiler_id, "QEMU", 4);
1212 #else
1213 memcpy(h->asl_compiler_id, "BXPC", 4);
1214 #endif
1215 h->asl_compiler_revision = cpu_to_le32(1);
1216 h->checksum = acpi_checksum((void *)h, len);
1219 /* base_addr must be a multiple of 4KB */
1220 void acpi_bios_init(void)
1222 struct rsdp_descriptor *rsdp;
1223 struct rsdt_descriptor_rev1 *rsdt;
1224 struct fadt_descriptor_rev1 *fadt;
1225 struct facs_descriptor_rev1 *facs;
1226 struct multiple_apic_table *madt;
1227 uint8_t *dsdt;
1228 uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
1229 uint32_t acpi_tables_size, madt_addr, madt_size;
1230 int i;
1232 /* reserve memory space for tables */
1233 #ifdef BX_USE_EBDA_TABLES
1234 ebda_cur_addr = align(ebda_cur_addr, 16);
1235 rsdp = (void *)(ebda_cur_addr);
1236 ebda_cur_addr += sizeof(*rsdp);
1237 #else
1238 bios_table_cur_addr = align(bios_table_cur_addr, 16);
1239 rsdp = (void *)(bios_table_cur_addr);
1240 bios_table_cur_addr += sizeof(*rsdp);
1241 #endif
1243 addr = base_addr = ram_size - ACPI_DATA_SIZE;
1244 rsdt_addr = addr;
1245 rsdt = (void *)(addr);
1246 addr += sizeof(*rsdt);
1248 fadt_addr = addr;
1249 fadt = (void *)(addr);
1250 addr += sizeof(*fadt);
1252 /* XXX: FACS should be in RAM */
1253 addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
1254 facs_addr = addr;
1255 facs = (void *)(addr);
1256 addr += sizeof(*facs);
1258 dsdt_addr = addr;
1259 dsdt = (void *)(addr);
1260 addr += sizeof(AmlCode);
1262 addr = (addr + 7) & ~7;
1263 madt_addr = addr;
1264 madt_size = sizeof(*madt) +
1265 sizeof(struct madt_processor_apic) * smp_cpus +
1266 sizeof(struct madt_io_apic);
1267 madt = (void *)(addr);
1268 addr += madt_size;
1270 acpi_tables_size = addr - base_addr;
1272 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
1273 (unsigned long)rsdp,
1274 (unsigned long)rsdt, acpi_tables_size);
1276 /* RSDP */
1277 memset(rsdp, 0, sizeof(*rsdp));
1278 memcpy(rsdp->signature, "RSD PTR ", 8);
1279 #ifdef BX_QEMU
1280 memcpy(rsdp->oem_id, "QEMU ", 6);
1281 #else
1282 memcpy(rsdp->oem_id, "BOCHS ", 6);
1283 #endif
1284 rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
1285 rsdp->checksum = acpi_checksum((void *)rsdp, 20);
1287 /* RSDT */
1288 memset(rsdt, 0, sizeof(*rsdt));
1289 rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
1290 rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
1291 acpi_build_table_header((struct acpi_table_header *)rsdt,
1292 "RSDT", sizeof(*rsdt));
1294 /* FADT */
1295 memset(fadt, 0, sizeof(*fadt));
1296 fadt->firmware_ctrl = cpu_to_le32(facs_addr);
1297 fadt->dsdt = cpu_to_le32(dsdt_addr);
1298 fadt->model = 1;
1299 fadt->reserved1 = 0;
1300 fadt->sci_int = cpu_to_le16(pm_sci_int);
1301 fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
1302 fadt->acpi_enable = 0xf1;
1303 fadt->acpi_disable = 0xf0;
1304 fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
1305 fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
1306 fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
1307 fadt->pm1_evt_len = 4;
1308 fadt->pm1_cnt_len = 2;
1309 fadt->pm_tmr_len = 4;
1310 fadt->plvl2_lat = cpu_to_le16(50);
1311 fadt->plvl3_lat = cpu_to_le16(50);
1312 fadt->plvl3_lat = cpu_to_le16(50);
1313 /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
1314 fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
1315 acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
1316 sizeof(*fadt));
1318 /* FACS */
1319 memset(facs, 0, sizeof(*facs));
1320 memcpy(facs->signature, "FACS", 4);
1321 facs->length = cpu_to_le32(sizeof(*facs));
1323 /* DSDT */
1324 memcpy(dsdt, AmlCode, sizeof(AmlCode));
1326 /* MADT */
1328 struct madt_processor_apic *apic;
1329 struct madt_io_apic *io_apic;
1331 memset(madt, 0, madt_size);
1332 madt->local_apic_address = cpu_to_le32(0xfee00000);
1333 madt->flags = cpu_to_le32(1);
1334 apic = (void *)(madt + 1);
1335 for(i=0;i<smp_cpus;i++) {
1336 apic->type = APIC_PROCESSOR;
1337 apic->length = sizeof(*apic);
1338 apic->processor_id = i;
1339 apic->local_apic_id = i;
1340 apic->flags = cpu_to_le32(1);
1341 apic++;
1343 io_apic = (void *)apic;
1344 io_apic->type = APIC_IO;
1345 io_apic->length = sizeof(*io_apic);
1346 io_apic->io_apic_id = smp_cpus;
1347 io_apic->address = cpu_to_le32(0xfec00000);
1348 io_apic->interrupt = cpu_to_le32(0);
1350 acpi_build_table_header((struct acpi_table_header *)madt,
1351 "APIC", madt_size);
1355 void rombios32_init(void)
1357 BX_INFO("Starting rombios32\n");
1359 ram_probe();
1361 cpu_probe();
1363 smp_probe();
1365 pci_bios_init();
1367 if (bios_table_cur_addr != 0) {
1369 mptable_init();
1371 if (acpi_enabled)
1372 acpi_bios_init();
1374 bios_lock_shadow_ram();