14d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/////////////////////////////////////////////////////////////////////////
24d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima// $Id$
34d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/////////////////////////////////////////////////////////////////////////
44d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//
54d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  32 bit Bochs BIOS init code
64d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  Copyright (C) 2006 Fabrice Bellard
74d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//
84d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  This library is free software; you can redistribute it and/or
94d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  modify it under the terms of the GNU Lesser General Public
104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  License as published by the Free Software Foundation; either
114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  version 2 of the License, or (at your option) any later version.
124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//
134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  This library is distributed in the hope that it will be useful,
144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  but WITHOUT ANY WARRANTY; without even the implied warranty of
154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  Lesser General Public License for more details.
174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//
184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  You should have received a copy of the GNU Lesser General Public
194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  License along with this library; if not, write to the Free Software
204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#include <stdarg.h>
224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#include <stddef.h>
234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#include "rombios.h"
254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef signed char  int8_t;
274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef short int16_t;
284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef int   int32_t;
294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef long long int64_t;
304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef unsigned char  uint8_t;
314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef unsigned short uint16_t;
324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef unsigned int   uint32_t;
334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef unsigned long long uint64_t;
344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* if true, put the MP float table and ACPI RSDT in EBDA and the MP
364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   table in RAM. Unfortunately, Linux has bugs with that, so we prefer
374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   to modify the BIOS in shadow RAM */
384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima//#define BX_USE_EBDA_TABLES
394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* define it if the (emulated) hardware supports SMM mode */
414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define BX_USE_SMM
424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define cpuid(index, eax, ebx, ecx, edx) \
444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  asm volatile ("cpuid" \
454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                : "0" (index))
474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define wbinvd() asm volatile("wbinvd")
494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define CPUID_MSR (1 << 5)
514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define CPUID_APIC (1 << 9)
524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define CPUID_MTRR (1 << 12)
534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_BASE    ((uint8_t *)0xfee00000)
554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_ICR_LOW 0x300
564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_SVR     0x0F0
574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_ID      0x020
584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_LVT3    0x370
594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_ENABLED 0x0100
614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define AP_BOOT_ADDR 0x9f000
634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MPTABLE_MAX_SIZE  0x00002000
654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define SMI_CMD_IO_ADDR   0xb2
664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define BIOS_TMP_STORAGE  0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRcap                     0x000000fe
704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix64K_00000            0x00000250
714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix16K_80000            0x00000258
724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix16K_A0000            0x00000259
734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_C0000             0x00000268
744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_C8000             0x00000269
754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_D0000             0x0000026a
764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_D8000             0x0000026b
774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_E0000             0x0000026c
784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_E8000             0x0000026d
794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_F0000             0x0000026e
804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRfix4K_F8000             0x0000026f
814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MSR_MTRRdefType                 0x000002ff
824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void outl(int addr, int val)
874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val));
894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void outw(int addr, int val)
924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("outw %w1, %w0" : : "d" (addr), "a" (val));
944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void outb(int addr, int val)
974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("outb %b1, %w0" : : "d" (addr), "a" (val));
994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint32_t inl(int addr)
1024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t val;
1044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("inl %w1, %0" : "=a" (val) : "d" (addr));
1054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return val;
1064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint16_t inw(int addr)
1094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t val;
1114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("inw %w1, %w0" : "=a" (val) : "d" (addr));
1124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return val;
1134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint8_t inb(int addr)
1164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t val;
1184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("inb %w1, %b0" : "=a" (val) : "d" (addr));
1194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return val;
1204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void writel(void *addr, uint32_t val)
1234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(volatile uint32_t *)addr = val;
1254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void writew(void *addr, uint16_t val)
1284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(volatile uint16_t *)addr = val;
1304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void writeb(void *addr, uint8_t val)
1334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(volatile uint8_t *)addr = val;
1354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint32_t readl(const void *addr)
1384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return *(volatile const uint32_t *)addr;
1404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint16_t readw(const void *addr)
1434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return *(volatile const uint16_t *)addr;
1454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint8_t readb(const void *addr)
1484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return *(volatile const uint8_t *)addr;
1504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline void putc(int c)
1534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outb(INFO_PORT, c);
1554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint64_t rdmsr(unsigned index)
1584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    unsigned long long ret;
1604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm ("rdmsr" : "=A"(ret) : "c"(index));
1624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return ret;
1634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void wrmsr(unsigned index, uint64_t val)
1664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    asm volatile ("wrmsr" : : "c"(index), "A"(val));
1684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline int isdigit(int c)
1714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return c >= '0' && c <= '9';
1734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid *memset(void *d1, int val, size_t len)
1764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *d = d1;
1784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (len--) {
1804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *d++ = val;
1814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
1824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return d1;
1834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid *memcpy(void *d1, const void *s1, size_t len)
1864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *d = d1;
1884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const uint8_t *s = s1;
1894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (len--) {
1914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *d++ = *s++;
1924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
1934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return d1;
1944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
1954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
1964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid *memmove(void *d1, const void *s1, size_t len)
1974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
1984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *d = d1;
1994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const uint8_t *s = s1;
2004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (d <= s) {
2024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        while (len--) {
2034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *d++ = *s++;
2044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
2054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else {
2064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        d += len;
2074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        s += len;
2084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        while (len--) {
2094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *--d = *--s;
2104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
2114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
2124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return d1;
2134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
2144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint memcmp(const void *s1, const void *s2, size_t len)
2164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
2174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const int8_t *p1 = s1;
2184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const int8_t *p2 = s2;
2194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (len--) {
2214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int r = *p1++ - *p2++;
2224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if(r)
2234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            return r;
2244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
2254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 0;
2274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
2284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasize_t strlen(const char *s)
2304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
2314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const char *s1;
2324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(s1 = s; *s1 != '\0'; s1++);
2334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return s1 - s;
2344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
2354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* from BSD ppp sources */
2374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
2384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
2394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int c, i, n;
2404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int width, prec, fillch;
2414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int base, len, neg;
2424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    unsigned long val = 0;
2434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const char *f;
2444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *str, *buf0;
2454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char num[32];
2464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    static const char hexchars[] = "0123456789abcdef";
2474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
2484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    buf0 = buf;
2494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    --buflen;
2504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (buflen > 0) {
2514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	for (f = fmt; *f != '%' && *f != 0; ++f)
2524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    ;
2534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (f > fmt) {
2544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    len = f - fmt;
2554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (len > buflen)
2564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		len = buflen;
2574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    memcpy(buf, fmt, len);
2584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    buf += len;
2594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    buflen -= len;
2604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    fmt = f;
2614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
2624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (*fmt == 0)
2634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
2644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	c = *++fmt;
2654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	width = prec = 0;
2664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	fillch = ' ';
2674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (c == '0') {
2684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    fillch = '0';
2694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    c = *++fmt;
2704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
2714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (c == '*') {
2724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    width = va_arg(args, int);
2734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    c = *++fmt;
2744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	} else {
2754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    while (isdigit(c)) {
2764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		width = width * 10 + c - '0';
2774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		c = *++fmt;
2784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    }
2794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
2804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (c == '.') {
2814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    c = *++fmt;
2824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (c == '*') {
2834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		prec = va_arg(args, int);
2844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		c = *++fmt;
2854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    } else {
2864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		while (isdigit(c)) {
2874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		    prec = prec * 10 + c - '0';
2884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		    c = *++fmt;
2894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		}
2904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    }
2914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
2924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* modifiers */
2934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        switch(c) {
2944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        case 'l':
2954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            c = *++fmt;
2964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            break;
2974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        default:
2984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            break;
2994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
3004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        str = 0;
3014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	base = 0;
3024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	neg = 0;
3034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	++fmt;
3044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	switch (c) {
3054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'd':
3064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    i = va_arg(args, int);
3074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (i < 0) {
3084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		neg = 1;
3094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		val = -i;
3104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    } else
3114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		val = i;
3124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    base = 10;
3134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'o':
3154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    val = va_arg(args, unsigned int);
3164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    base = 8;
3174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'x':
3194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'X':
3204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    val = va_arg(args, unsigned int);
3214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    base = 16;
3224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'p':
3244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    val = (unsigned long) va_arg(args, void *);
3254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    base = 16;
3264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    neg = 2;
3274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 's':
3294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    str = va_arg(args, char *);
3304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	case 'c':
3324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    num[0] = va_arg(args, int);
3334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    num[1] = 0;
3344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    str = num;
3354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    break;
3364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	default:
3374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    *buf++ = '%';
3384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (c != '%')
3394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		--fmt;		/* so %z outputs %z etc. */
3404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    --buflen;
3414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    continue;
3424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
3434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (base != 0) {
3444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    str = num + sizeof(num);
3454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    *--str = 0;
3464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    while (str > num + neg) {
3474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		*--str = hexchars[val % base];
3484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		val = val / base;
3494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		if (--prec <= 0 && val == 0)
3504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		    break;
3514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    }
3524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    switch (neg) {
3534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    case 1:
3544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		*--str = '-';
3554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		break;
3564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    case 2:
3574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		*--str = 'x';
3584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		*--str = '0';
3594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		break;
3604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    }
3614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    len = num + sizeof(num) - 1 - str;
3624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	} else {
3634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    len = strlen(str);
3644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (prec > 0 && len > prec)
3654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		len = prec;
3664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
3674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (width > 0) {
3684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if (width > buflen)
3694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		width = buflen;
3704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    if ((n = width - len) > 0) {
3714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		buflen -= n;
3724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		for (; n > 0; --n)
3734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima		    *buf++ = fillch;
3744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    }
3754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	}
3764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	if (len > buflen)
3774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	    len = buflen;
3784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	memcpy(buf, str, len);
3794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	buf += len;
3804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	buflen -= len;
3814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
3824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *buf = 0;
3834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return buf - buf0;
3844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
3854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
3864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint snprintf(char * buf, size_t size, const char *fmt, ...)
3874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
3884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	va_list args;
3894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	int i;
3904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
3914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	va_start(args, fmt);
3924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	i=vsnprintf(buf,size,fmt,args);
3934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	va_end(args);
3944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	return i;
3954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
3964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
3974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid bios_printf(int flags, const char *fmt, ...)
3984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
3994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    va_list ap;
4004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char buf[1024];
4014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    const char *s;
4024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if ((flags & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT)
4044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        outb(PANIC_PORT2, 0x00);
4054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    va_start(ap, fmt);
4074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vsnprintf(buf, sizeof(buf), fmt, ap);
4084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    s = buf;
4094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (*s)
4104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putc(*s++);
4114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    va_end(ap);
4124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
4134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid delay_ms(int n)
4154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
4164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i, j;
4174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i = 0; i < n; i++) {
4184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
4194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* approximative ! */
4204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for(j = 0; j < 1000000; j++);
4214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
4224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        {
4234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima          int r1, r2;
4244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima          j = 66;
4254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima          r1 = inb(0x61) & 0x10;
4264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima          do {
4274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            r2 = inb(0x61) & 0x10;
4284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (r1 != r2) {
4294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima              j--;
4304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima              r1 = r2;
4314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
4324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima          } while (j > 0);
4334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
4344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
4354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
4364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
4374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint16_t smp_cpus;
4394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint32_t cpuid_signature;
4404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint32_t cpuid_features;
4414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint32_t cpuid_ext_features;
4424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaunsigned long ram_size;
4434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint64_t ram_end;
4444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
4454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaunsigned long ebda_cur_addr;
4464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
4474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint acpi_enabled;
4484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint32_t pm_io_base, smb_io_base;
4494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint pm_sci_int;
4504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaunsigned long bios_table_cur_addr;
4514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaunsigned long bios_table_end_addr;
4524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint64_t le64_to_cpu(uint64_t x)
4544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
4554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return x;
4564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
4574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid wrmsr_smp(uint32_t index, uint64_t val)
4594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
4604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    static struct { uint32_t ecx, eax, edx; } *p = (void *)SMP_MSR_ADDR;
4614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr(index, val);
4634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->ecx = index;
4644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->eax = val;
4654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->edx = val >> 32;
4664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ++p;
4674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->ecx = 0;
4684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
4694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
4714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_CTL_PORT 0x510
4724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_DATA_PORT 0x511
4734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_SIGNATURE  0x00
4744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_ID         0x01
4754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_UUID       0x02
4764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_NUMA       0x0D
4774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_ARCH_LOCAL     0x8000
4784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_ACPI_TABLES  (QEMU_CFG_ARCH_LOCAL + 0)
4794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define QEMU_CFG_SMBIOS_ENTRIES  (QEMU_CFG_ARCH_LOCAL + 1)
4804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint qemu_cfg_port;
4824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid qemu_cfg_select(int f)
4844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
4854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outw(QEMU_CFG_CTL_PORT, f);
4864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
4874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint qemu_cfg_port_probe()
4894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
4904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *sig = "QEMU";
4914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i;
4924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_select(QEMU_CFG_SIGNATURE);
4944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0; i < 4; i++)
4964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (inb(QEMU_CFG_DATA_PORT) != sig[i])
4974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            return 0;
4984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
4994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 1;
5004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid qemu_cfg_read(uint8_t *buf, int len)
5034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (len--)
5054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(buf++) = inb(QEMU_CFG_DATA_PORT);
5064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint16_t acpi_additional_tables(void)
5094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t cnt;
5114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_select(QEMU_CFG_ACPI_TABLES);
5134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
5144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return cnt;
5164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int acpi_load_table(int i, uint32_t addr, uint16_t *len)
5194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_read((uint8_t*)len, sizeof(*len));
5214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!*len)
5234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return -1;
5244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_read((uint8_t*)addr, *len);
5264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 0;
5274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint16_t smbios_entries(void)
5304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t cnt;
5324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_select(QEMU_CFG_SMBIOS_ENTRIES);
5344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
5354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return cnt;
5374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimauint64_t qemu_cfg_get64 (void)
5404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint64_t ret;
5424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_read((uint8_t*)&ret, 8);
5444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return le64_to_cpu(ret);
5454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
5474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid cpu_probe(void)
5494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t eax, ebx, ecx, edx;
5514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cpuid(1, eax, ebx, ecx, edx);
5524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cpuid_signature = eax;
5534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cpuid_features = edx;
5544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cpuid_ext_features = ecx;
5554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int cmos_readb(int addr)
5584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outb(0x70, addr);
5604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return inb(0x71);
5614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
5624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid setup_mtrr(void)
5644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
5654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i, vcnt, fix, wc;
5664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t mtrr_cap;
5674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    union {
5684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint8_t valb[8];
5694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint64_t val;
5704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } u;
5714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(uint32_t *)SMP_MSR_ADDR = 0;
5734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!(cpuid_features & CPUID_MTRR))
5754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return;
5764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!(cpuid_features & CPUID_MSR))
5784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return;
5794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mtrr_cap = rdmsr(MSR_MTRRcap);
5814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vcnt = mtrr_cap & 0xff;
5824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fix = mtrr_cap & 0x100;
5834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wc = mtrr_cap & 0x400;
5844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!vcnt || !fix)
5854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return;
5864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
5874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    u.val = 0;
5884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0; i < 8; ++i)
5894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (ram_size >= 65536 * (i + 1))
5904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            u.valb[i] = 6;
5914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
5924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    u.val = 0;
5934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0; i < 8; ++i)
5944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (ram_size >= 65536 * 8 + 16384 * (i + 1))
5954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            u.valb[i] = 6;
5964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
5974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
5984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
5994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
6004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
6014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
6024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
6034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
6044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
6054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
6064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
6074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
6084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
6094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wrmsr_smp(MSR_MTRRdefType, 0xc06);
6104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
6114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid ram_probe(void)
6134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
6144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  if (cmos_readb(0x34) | cmos_readb(0x35))
6154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ram_size = (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
6164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        16 * 1024 * 1024;
6174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  else
6184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ram_size = (cmos_readb(0x30) | (cmos_readb(0x31) << 8)) * 1024 +
6194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        1 * 1024 * 1024;
6204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  BX_INFO("ram_size=0x%08lx\n", ram_size);
6214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
6224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ram_end = (((uint64_t)cmos_readb(0x5b) << 16) |
6234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima               ((uint64_t)cmos_readb(0x5c) << 24) |
6244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima               ((uint64_t)cmos_readb(0x5d) << 32)) + (1ull << 32);
6254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  else
6264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ram_end = ram_size;
6274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  BX_INFO("end of ram=%ldMB\n", ram_end >> 20);
6284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
6294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
6304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima  BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
6314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
6324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
6334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/****************************************************/
6354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMP probe */
6364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaextern uint8_t smp_ap_boot_code_start;
6384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaextern uint8_t smp_ap_boot_code_end;
6394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* find the number of CPUs by launching a SIPI to them */
6414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid smp_probe(void)
6424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
6434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t val, sipi_vector;
6444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    writew(&smp_cpus, 1);
6464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (cpuid_features & CPUID_APIC) {
6474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* enable local APIC */
6494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        val = readl(APIC_BASE + APIC_SVR);
6504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        val |= APIC_ENABLED;
6514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        writel(APIC_BASE + APIC_SVR, val);
6524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* copy AP boot code */
6544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start,
6554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima               &smp_ap_boot_code_end - &smp_ap_boot_code_start);
6564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* broadcast SIPI */
6584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500);
6594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sipi_vector = AP_BOOT_ADDR >> 12;
6604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector);
6614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifndef BX_QEMU
6634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        delay_ms(10);
6644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
6654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        while (cmos_readb(0x5f) + 1 != readw(&smp_cpus))
6664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            ;
6674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
6684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
6694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("Found %d cpu(s)\n", readw(&smp_cpus));
6704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
6714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/****************************************************/
6734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* PCI init */
6744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_ADDRESS_SPACE_MEM		0x00
6764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_ADDRESS_SPACE_IO		0x01
6774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
6784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_ROM_SLOT 6
6804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_NUM_REGIONS 7
6814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICES_MAX 64
6834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_VENDOR_ID		0x00	/* 16 bits */
6854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID		0x02	/* 16 bits */
6864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_COMMAND		0x04	/* 16 bits */
6874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
6884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
6894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_CLASS_DEVICE        0x0a    /* Device class */
6904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
6914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
6924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_MIN_GNT		0x3e	/* 8 bits */
6934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_MAX_LAT		0x3f	/* 8 bits */
6944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
6954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_VENDOR_ID_INTEL             0x8086
6964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82441       0x1237
6974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82371SB_0   0x7000
6984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82371SB_1   0x7010
6994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82371AB_0   0x7110
7004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82371AB     0x7111
7014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_DEVICE_ID_INTEL_82371AB_3   0x7113
7024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_VENDOR_ID_IBM               0x1014
7044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define PCI_VENDOR_ID_APPLE             0x106b
7054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimatypedef struct PCIDevice {
7074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int bus;
7084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int devfn;
7094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} PCIDevice;
7104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_bios_io_addr;
7124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_bios_mem_addr;
7134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_bios_bigmem_addr;
7144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* host irqs corresponding to PCI irqs A-D */
7154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
7164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic PCIDevice i440_pcidev;
7174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
7194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcfc, val);
7224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
7254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outw(0xcfc + (addr & 2), val);
7284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
7314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outb(0xcfc + (addr & 3), val);
7344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
7374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return inl(0xcfc);
7404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
7434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return inw(0xcfc + (addr & 2));
7464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
7494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
7514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return inb(0xcfc + (addr & 3));
7524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
7554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t cmd;
7574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t ofs, old_addr;
7584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if ( region_num == PCI_ROM_SLOT ) {
7604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        ofs = 0x30;
7614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }else{
7624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        ofs = 0x10 + region_num * 4;
7634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
7644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    old_addr = pci_config_readl(d, ofs);
7664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_config_writel(d, ofs, addr);
7684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("region %d: 0x%08x\n", region_num, addr);
7694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* enable memory mappings */
7714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cmd = pci_config_readw(d, PCI_COMMAND);
7724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if ( region_num == PCI_ROM_SLOT )
7734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        cmd |= 2;
7744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    else if (old_addr & PCI_ADDRESS_SPACE_IO)
7754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        cmd |= 1;
7764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    else
7774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        cmd |= 2;
7784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_config_writew(d, PCI_COMMAND, cmd);
7794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* return the global irq number corresponding to a given device irq
7824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   pin. We could also use the bus number to have a more precise
7834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   mapping. */
7844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
7854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int slot_addend;
7874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    slot_addend = (pci_dev->devfn >> 3) - 1;
7884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return (irq_num + slot_addend) & 3;
7894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
7904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
7914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void find_bios_table_area(void)
7924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
7934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    unsigned long addr;
7944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(addr = 0xf0000; addr < 0x100000; addr += 16) {
7954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (*(uint32_t *)addr == 0xaafb4442) {
7964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            bios_table_cur_addr = addr + 8;
7974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4);
7984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
7994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    bios_table_cur_addr, bios_table_end_addr);
8004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            return;
8014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
8024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
8034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return;
8044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
8054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void bios_shadow_init(PCIDevice *d)
8074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
8084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int v;
8094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (bios_table_cur_addr == 0)
8114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return;
8124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* remap the BIOS to shadow RAM an keep it read/write while we
8144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima       are writing tables */
8154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    v = pci_config_readb(d, 0x59);
8164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    v &= 0xcf;
8174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_config_writeb(d, 0x59, v);
8184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
8194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    v |= 0x30;
8204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_config_writeb(d, 0x59, v);
8214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
8224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    i440_pcidev = *d;
8244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
8254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void bios_lock_shadow_ram(void)
8274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
8284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    PCIDevice *d = &i440_pcidev;
8294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int v;
8304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    wbinvd();
8324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    v = pci_config_readb(d, 0x59);
8334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    v = (v & 0x0f) | (0x10);
8344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_config_writeb(d, 0x59, v);
8354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
8364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_bios_init_bridges(PCIDevice *d)
8384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
8394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t vendor_id, device_id;
8404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
8424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    device_id = pci_config_readw(d, PCI_DEVICE_ID);
8434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (vendor_id == PCI_VENDOR_ID_INTEL &&
8454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima       (device_id == PCI_DEVICE_ID_INTEL_82371SB_0 ||
8464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
8474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int i, irq;
8484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint8_t elcr[2];
8494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* PIIX3/PIIX4 PCI to ISA bridge */
8514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        elcr[0] = 0x00;
8534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        elcr[1] = 0x00;
8544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for(i = 0; i < 4; i++) {
8554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            irq = pci_irqs[i];
8564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* set to trigger level */
8574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            elcr[irq >> 3] |= (1 << (irq & 7));
8584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* activate irq remapping in PIIX */
8594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_config_writeb(d, 0x60 + i, irq);
8604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
8614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        outb(0x4d0, elcr[0]);
8624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        outb(0x4d1, elcr[1]);
8634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        BX_INFO("PIIX3/PIIX4 init: elcr=%02x %02x\n",
8644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                elcr[0], elcr[1]);
8654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) {
8664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* i440 PCI bridge */
8674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        bios_shadow_init(d);
8684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
8694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
8704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaextern uint8_t smm_relocation_start, smm_relocation_end;
8724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaextern uint8_t smm_code_start, smm_code_end;
8734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_SMM
8754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void smm_init(PCIDevice *d)
8764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
8774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t value;
8784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* check if SMM init is already done */
8804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    value = pci_config_readl(d, 0x58);
8814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if ((value & (1 << 25)) == 0) {
8824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* enable the SMM memory window */
8844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
8854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* save original memory content */
8874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy((void *)0xa8000, (void *)0x38000, 0x8000);
8884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* copy the SMM relocation code */
8904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy((void *)0x38000, &smm_relocation_start,
8914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima               &smm_relocation_end - &smm_relocation_start);
8924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* enable SMI generation when writing to the APMC register */
8944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writel(d, 0x58, value | (1 << 25));
8954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* init APM status port */
8974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        outb(0xb3, 0x01);
8984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
8994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* raise an SMI interrupt */
9004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        outb(0xb2, 0x00);
9014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* wait until SMM code executed */
9034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        while (inb(0xb3) != 0x00);
9044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* restore original memory content */
9064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy((void *)0x38000, (void *)0xa8000, 0x8000);
9074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* copy the SMM code */
9094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy((void *)0xa8000, &smm_code_start,
9104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima               &smm_code_end - &smm_code_start);
9114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        wbinvd();
9124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* close the SMM memory window and enable normal SMM */
9144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
9154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
9164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
9174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
9184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void piix4_pm_enable(PCIDevice *d)
9204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
9214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* PIIX4 Power Management device (for ACPI) */
9224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writel(d, 0x40, PM_IO_BASE | 1);
9234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
9244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writel(d, 0x90, SMB_IO_BASE | 1);
9254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
9264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_SMM
9274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        smm_init(d);
9284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
9294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
9304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void pci_bios_init_device(PCIDevice *d)
9324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
9334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int class;
9344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t *paddr;
9354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i, pin, pic_irq, vendor_id, device_id;
9364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    class = pci_config_readw(d, PCI_CLASS_DEVICE);
9384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
9394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    device_id = pci_config_readw(d, PCI_DEVICE_ID);
9404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x class=0x%04x\n",
9414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            d->bus, d->devfn, vendor_id, device_id, class);
9424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    switch(class) {
9434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    case 0x0101: /* Mass storage controller - IDE interface */
9444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (vendor_id == PCI_VENDOR_ID_INTEL &&
9454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima           (device_id == PCI_DEVICE_ID_INTEL_82371SB_1 ||
9464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
9474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* PIIX3/PIIX4 IDE */
9484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_config_writew(d, 0x40, 0x8000); // enable IDE0
9494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_config_writew(d, 0x42, 0x8000); // enable IDE1
9504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            goto default_map;
9514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        } else {
9524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* IDE: we map it as in ISA mode */
9534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_set_io_region_addr(d, 0, 0x1f0);
9544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_set_io_region_addr(d, 1, 0x3f4);
9554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_set_io_region_addr(d, 2, 0x170);
9564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_set_io_region_addr(d, 3, 0x374);
9574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
9584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        break;
9594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    case 0x0300: /* Display controller - VGA compatible controller */
9604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (vendor_id != 0x1234)
9614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            goto default_map;
9624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* VGA: map frame buffer to default Bochs VBE address */
9634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_set_io_region_addr(d, 0, 0xE0000000);
9644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        break;
9654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    case 0x0800: /* Generic system peripheral - PIC */
9664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (vendor_id == PCI_VENDOR_ID_IBM) {
9674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* IBM */
9684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (device_id == 0x0046 || device_id == 0xFFFF) {
9694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                /* MPIC & MPIC2 */
9704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
9714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
9724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
9734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        break;
9744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    case 0xff00:
9754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (vendor_id == PCI_VENDOR_ID_APPLE &&
9764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (device_id == 0x0017 || device_id == 0x0022)) {
9774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* macio bridge */
9784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_set_io_region_addr(d, 0, 0x80800000);
9794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
9804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        break;
9814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    default:
9824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    default_map:
9834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* default memory mappings */
9844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for(i = 0; i < PCI_NUM_REGIONS; i++) {
9854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            int ofs;
9864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            uint32_t val, size ;
9874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
9884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (i == PCI_ROM_SLOT) {
9894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                ofs = 0x30;
9904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                pci_config_writel(d, ofs, 0xfffffffe);
9914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            } else {
9924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                ofs = 0x10 + i * 4;
9934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                pci_config_writel(d, ofs, 0xffffffff);
9944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
9954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            val = pci_config_readl(d, ofs);
9964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (val != 0) {
9974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                size = (~(val & ~0xf)) + 1;
9984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                if (val & PCI_ADDRESS_SPACE_IO)
9994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    paddr = &pci_bios_io_addr;
10004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                else if (size >= 0x04000000)
10014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    paddr = &pci_bios_bigmem_addr;
10024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                else
10034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    paddr = &pci_bios_mem_addr;
10044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                *paddr = (*paddr + size - 1) & ~(size - 1);
10054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                pci_set_io_region_addr(d, i, *paddr);
10064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                *paddr += size;
10074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
10084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
10094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        break;
10104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
10114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* map the interrupt */
10134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
10144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (pin != 0) {
10154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pin = pci_slot_get_pirq(d, pin - 1);
10164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pic_irq = pci_irqs[pin];
10174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
10184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
10194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
10214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* PIIX4 Power Management device (for ACPI) */
10224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pm_io_base = PM_IO_BASE;
10234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        smb_io_base = SMB_IO_BASE;
10244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        // acpi sci is hardwired to 9
10254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_config_writeb(d, PCI_INTERRUPT_LINE, 9);
10264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE);
10274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        piix4_pm_enable(d);
10284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        acpi_enabled = 1;
10294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
10304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid pci_for_each_device(void (*init_func)(PCIDevice *d))
10334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    PCIDevice d1, *d = &d1;
10354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int bus, devfn;
10364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t vendor_id, device_id;
10374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(bus = 0; bus < 1; bus++) {
10394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for(devfn = 0; devfn < 256; devfn++) {
10404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            d->bus = bus;
10414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            d->devfn = devfn;
10424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
10434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            device_id = pci_config_readw(d, PCI_DEVICE_ID);
10444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (vendor_id != 0xffff || device_id != 0xffff) {
10454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                init_func(d);
10464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
10474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
10484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
10494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid pci_bios_init(void)
10524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_bios_io_addr = 0xc000;
10544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_bios_mem_addr = 0xf0000000;
10554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_bios_bigmem_addr = ram_size;
10564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (pci_bios_bigmem_addr < 0x90000000)
10574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_bios_bigmem_addr = 0x90000000;
10584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_for_each_device(pci_bios_init_bridges);
10604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_for_each_device(pci_bios_init_device);
10624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/****************************************************/
10654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Multi Processor table init */
10664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void putb(uint8_t **pp, int val)
10684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *q;
10704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = *pp;
10714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val;
10724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *pp = q;
10734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void putstr(uint8_t **pp, const char *str)
10764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *q;
10784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = *pp;
10794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    while (*str)
10804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *q++ = *str++;
10814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *pp = q;
10824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void putle16(uint8_t **pp, int val)
10854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *q;
10874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = *pp;
10884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val;
10894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val >> 8;
10904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *pp = q;
10914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
10924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
10934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void putle32(uint8_t **pp, int val)
10944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
10954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *q;
10964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = *pp;
10974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val;
10984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val >> 8;
10994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val >> 16;
11004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *q++ = val >> 24;
11014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *pp = q;
11024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
11034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int mpf_checksum(const uint8_t *data, int len)
11054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
11064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int sum, i;
11074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    sum = 0;
11084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i = 0; i < len; i++)
11094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sum += data[i];
11104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return sum & 0xff;
11114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
11124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic unsigned long align(unsigned long addr, unsigned long v)
11144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
11154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return (addr + v - 1) & ~(v - 1);
11164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
11174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void mptable_init(void)
11194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
11204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *mp_config_table, *q, *float_pointer_struct;
11214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int ioapic_id, i, len;
11224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int mp_config_table_size;
11234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
11254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
11264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
11274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr = align(bios_table_cur_addr, 16);
11284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table = (uint8_t *)bios_table_cur_addr;
11294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
11304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = mp_config_table;
11314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "PCMP"); /* "PCMP signature */
11324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle16(&q, 0); /* table length (patched later) */
11334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 4); /* spec rev */
11344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* checksum (patched later) */
11354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
11364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "QEMUCPU "); /* OEM id */
11374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
11384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "BOCHSCPU");
11394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
11404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "0.1         "); /* vendor id */
11414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle32(&q, 0); /* OEM table ptr */
11424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle16(&q, 0); /* OEM table size */
11434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle16(&q, smp_cpus + 18); /* entry count */
11444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle32(&q, 0xfee00000); /* local APIC addr */
11454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle16(&q, 0); /* ext table length */
11464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* ext table checksum */
11474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* reserved */
11484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i = 0; i < smp_cpus; i++) {
11504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0); /* entry type = processor */
11514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, i); /* APIC id */
11524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0x11); /* local APIC version number */
11534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (i == 0)
11544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
11554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        else
11564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            putb(&q, 1); /* cpu flags: enabled */
11574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0); /* cpu signature */
11584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 6);
11594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0);
11604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0);
11614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0x201); /* feature flags */
11624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0);
11634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0); /* reserved */
11654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0);
11664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0);
11674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putle16(&q, 0);
11684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
11694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* isa bus */
11714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 1); /* entry type = bus */
11724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* bus ID */
11734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "ISA   ");
11744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* ioapic */
11764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ioapic_id = smp_cpus;
11774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 2); /* entry type = I/O APIC */
11784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, ioapic_id); /* apic ID */
11794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0x11); /* I/O APIC version number */
11804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 1); /* enable */
11814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle32(&q, 0xfec00000); /* I/O APIC addr */
11824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
11834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* irqs */
1184eb21efafc629759705de263d5b3da18ceb9a23b2Jiang, Yunhong    for(i = 0; i < 32; i++) {
11854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
11864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* One entry per ioapic input. Input 2 is covered by
11874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima           irq0->inti2 override (i == 0). irq 2 is unused */
11884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (i == 2)
11894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            continue;
11904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
11914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 3); /* entry type = I/O interrupt */
11924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0); /* interrupt type = vectored interrupt */
11934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0); /* flags: po=0, el=0 */
11944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0);
11954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, 0); /* source bus ID = ISA */
11964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, i); /* source bus IRQ */
11974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, ioapic_id); /* dest I/O APIC ID */
11984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
11994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, i == 0 ? 2 : i); /* dest I/O APIC interrupt in */
12004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
12014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        putb(&q, i); /* dest I/O APIC interrupt in */
12024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
12034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
12044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* patch length */
12054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    len = q - mp_config_table;
12064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table[4] = len;
12074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table[5] = len >> 8;
12084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
12104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    mp_config_table_size = q - mp_config_table;
12124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifndef BX_USE_EBDA_TABLES
12144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr += mp_config_table_size;
12154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
12164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* floating pointer structure */
12184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
12194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr = align(ebda_cur_addr, 16);
12204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    float_pointer_struct = (uint8_t *)ebda_cur_addr;
12214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
12224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr = align(bios_table_cur_addr, 16);
12234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    float_pointer_struct = (uint8_t *)bios_table_cur_addr;
12244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
12254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    q = float_pointer_struct;
12264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putstr(&q, "_MP_");
12274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* pointer to MP config table */
12284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putle32(&q, (unsigned long)mp_config_table);
12294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 1); /* length in 16 byte units */
12314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 4); /* MP spec revision */
12324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* checksum (patched later) */
12334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0); /* MP feature byte 1 */
12344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0);
12364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0);
12374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0);
12384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    putb(&q, 0);
12394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    float_pointer_struct[10] =
12404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
12414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
12424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr += (q - float_pointer_struct);
12434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
12444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr += (q - float_pointer_struct);
12454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
12464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
12474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (unsigned long)float_pointer_struct,
12484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (unsigned long)mp_config_table,
12494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            mp_config_table_size);
12504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
12514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/****************************************************/
12534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* ACPI tables init */
12544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Table structure from Linux kernel (the ACPI tables are under the
12564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   BSD license) */
12574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
12594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * All tables must be byte-packed to match the ACPI specification, since
12604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * the tables are provided by the system BIOS.
12614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
12624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
12644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            signature [4];          /* ACPI signature (4 ASCII characters) */\
12654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             length;                 /* Length of table, in bytes, including header */\
12664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              revision;               /* ACPI Specification minor version # */\
12674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              checksum;               /* To make sum of entire table == 0 */\
12684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            oem_id [6];             /* OEM identification */\
12694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            oem_table_id [8];       /* OEM table identification */\
12704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             oem_revision;           /* OEM revision number */\
12714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            asl_compiler_id [4];    /* ASL compiler vendor ID */\
12724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             asl_compiler_revision;  /* ASL compiler revision number */
12734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct acpi_table_header         /* ACPI common table header */
12764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
12774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_TABLE_HEADER_DEF
12784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
12794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct rsdp_descriptor         /* Root System Descriptor Pointer */
12814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
12824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            signature [8];          /* ACPI signature, contains "RSD PTR " */
12834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              checksum;               /* To make sum of struct == 0 */
12844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            oem_id [6];             /* OEM identification */
12854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              revision;               /* Must be 0 for 1.0, 2 for 2.0 */
12864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             rsdt_physical_address;  /* 32-bit physical address of RSDT */
12874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             length;                 /* XSDT Length in bytes including hdr */
12884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint64_t                             xsdt_physical_address;  /* 64-bit physical address of XSDT */
12894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              extended_checksum;      /* Checksum of entire table */
12904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            reserved [3];           /* Reserved field must be 0 */
12914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
12924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
12934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
12944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * ACPI 1.0 Root System Description Table (RSDT)
12954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
12964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct rsdt_descriptor_rev1
12974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
12984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
12994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
13004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             table_offset_entry [5]; /* Array of pointers to other */
13014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
13024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             table_offset_entry [3]; /* Array of pointers to other */
13034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
13044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima			 /* ACPI tables */
13054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
13064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
13084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * ACPI 1.0 Firmware ACPI Control Structure (FACS)
13094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
13104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct facs_descriptor_rev1
13114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
13124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                            signature[4];           /* ACPI Signature */
13134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             length;                 /* Length of structure, in bytes */
13144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             hardware_signature;     /* Hardware configuration signature */
13154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             firmware_waking_vector; /* ACPI OS waking vector */
13164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             global_lock;            /* Global Lock */
13174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
13184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             reserved1       : 31;   /* Must be 0 */
13194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              resverved3 [40];        /* Reserved - must be zero */
13204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
13214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
13244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * ACPI 1.0 Fixed ACPI Description Table (FADT)
13254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
13264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct fadt_descriptor_rev1
13274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
13284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
13294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             firmware_ctrl;          /* Physical address of FACS */
13304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             dsdt;                   /* Physical address of DSDT */
13314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              model;                  /* System Interrupt Model */
13324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved1;              /* Reserved */
13334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t                             sci_int;                /* System vector of SCI interrupt */
13344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             smi_cmd;                /* Port address of SMI command port */
13354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
13364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
13374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
13384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved2;              /* Reserved - must be zero */
13394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
13404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
13414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
13424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
13434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
13444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
13454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
13464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
13474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
13484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
13494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
13504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              pm_tmr_len;              /* Byte Length of ports at pm_tm_blk */
13514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
13524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
13534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              gpe1_base;              /* Offset in gpe model where gpe1 events start */
13544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved3;              /* Reserved */
13554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t                             plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
13564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t                             plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
13574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t                             flush_size;             /* Size of area read to flush caches */
13584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t                             flush_stride;           /* Stride used in flushing caches */
13594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
13604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              duty_width;             /* Bit width of duty cycle field in p_cnt reg */
13614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
13624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
13634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              century;                /* Index to century in RTC CMOS RAM */
13644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved4;              /* Reserved */
13654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved4a;             /* Reserved */
13664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved4b;             /* Reserved */
13674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#if 0
13684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             wb_invd         : 1;    /* The wbinvd instruction works properly */
13694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             wb_invd_flush   : 1;    /* The wbinvd flushes but does not invalidate */
13704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             proc_c1         : 1;    /* All processors support C1 state */
13714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             plvl2_up        : 1;    /* C2 state works on MP system */
13724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             pwr_button      : 1;    /* Power button is handled as a generic feature */
13734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             sleep_button    : 1;    /* Sleep button is handled as a generic feature, or not present */
13744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             fixed_rTC       : 1;    /* RTC wakeup stat not in fixed register space */
13754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             rtcs4           : 1;    /* RTC wakeup stat not possible from S4 */
13764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             tmr_val_ext     : 1;    /* The tmr_val width is 32 bits (0 = 24 bits) */
13774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             reserved5       : 23;   /* Reserved - must be zero */
13784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
13794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint32_t flags;
13804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
13814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
13824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
13844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * MADT values and structures
13854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
13864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Values for MADT PCATCompat */
13884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define DUAL_PIC                0
13904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define MULTIPLE_APIC           1
13914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Master MADT */
13944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
13954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct multiple_apic_table
13964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
13974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
13984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             local_apic_address;     /* Physical address of local APIC */
13994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#if 0
14004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             PCATcompat      : 1;    /* A one indicates system also has dual 8259s */
14014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             reserved1       : 31;
14024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
14034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint32_t                             flags;
14044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
14054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
14064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Values for Type in APIC sub-headers */
14094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_PROCESSOR          0
14114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_IO                 1
14124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_XRUPT_OVERRIDE     2
14134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_NMI                3
14144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_LOCAL_NMI          4
14154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_ADDRESS_OVERRIDE   5
14164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_IO_SAPIC           6
14174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_LOCAL_SAPIC        7
14184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_XRUPT_SOURCE       8
14194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define APIC_RESERVED           9           /* 9 and greater are reserved */
14204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define ACPI_SUB_HEADER_DEF                 /* Common ACPI sub-structure header */\
14224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              type; \
14234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              length;
14244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
14264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
14274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
14284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Sub-structures for MADT */
14294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct madt_processor_apic
14314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
14324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_SUB_HEADER_DEF
14334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              processor_id;           /* ACPI processor id */
14344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              local_apic_id;          /* Processor's local APIC id */
14354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#if 0
14364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             processor_enabled: 1;   /* Processor is usable if set */
14374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             reserved2       : 31;   /* Reserved, must be zero */
14384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
14394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint32_t flags;
14404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
14414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
14424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
14444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima * SRAT (NUMA topology description) table
14454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
14464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define SRAT_PROCESSOR          0
14484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define SRAT_MEMORY             1
14494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct system_resource_affinity_table
14514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
14524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ACPI_TABLE_HEADER_DEF
14534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    reserved1;
14544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    reserved2[2];
14554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima};
14564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct srat_processor_affinity
14584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
14594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ACPI_SUB_HEADER_DEF
14604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t     proximity_lo;
14614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t     local_apic_id;
14624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    flags;
14634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t     local_sapic_eid;
14644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t     proximity_hi[3];
14654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    reserved;
14664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima};
14674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct srat_memory_affinity
14694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
14704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ACPI_SUB_HEADER_DEF
14714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t     proximity[4];
14724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t    reserved1;
14734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    base_addr_low,base_addr_high;
14744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    length_low,length_high;
14754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    reserved2;
14764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    flags;
14774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t    reserved3[2];
14784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima};
14794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
14814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
14824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *  * ACPI 2.0 Generic Address Space definition.
14834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *   */
14844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct acpi_20_generic_address {
14854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t  address_space_id;
14864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t  register_bit_width;
14874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t  register_bit_offset;
14884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t  reserved;
14894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint64_t address;
14904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
14914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
14924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/*
14934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *  * HPET Description Table
14944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *   */
14954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct acpi_20_hpet {
14964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
14974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t           timer_block_id;
14984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct acpi_20_generic_address addr;
14994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t            hpet_number;
15004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t           min_tick;
15014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t            page_protect;
15024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
15034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define ACPI_HPET_ADDRESS 0xFED00000UL
15044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
15054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct madt_io_apic
15074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_SUB_HEADER_DEF
15094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              io_apic_id;             /* I/O APIC ID */
15104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                              reserved;               /* Reserved - must be zero */
15114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             address;                /* APIC physical address */
15124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t                             interrupt;              /* Global system interrupt where INTI
15134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima			  * lines start */
15144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
15154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
15174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct madt_int_override
15184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	ACPI_SUB_HEADER_DEF
15204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                bus;     /* Identifies ISA Bus */
15214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t                source;  /* Bus-relative interrupt source */
15224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t               gsi;     /* GSI that source will signal */
15234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t               flags;   /* MPS INTI flags */
15244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
15254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
15264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#include "acpi-dsdt.hex"
15284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint16_t cpu_to_le16(uint16_t x)
15304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return x;
15324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
15334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic inline uint32_t cpu_to_le32(uint32_t x)
15354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return x;
15374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
15384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int acpi_checksum(const uint8_t *data, int len)
15404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int sum, i;
15424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    sum = 0;
15434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i = 0; i < len; i++)
15444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sum += data[i];
15454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return (-sum) & 0xff;
15464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
15474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void acpi_build_table_header(struct acpi_table_header *h,
15494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                    char *sig, int len, uint8_t rev)
15504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->signature, sig, 4);
15524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    h->length = cpu_to_le32(len);
15534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    h->revision = rev;
15544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
15554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->oem_id, "QEMU  ", 6);
15564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->oem_table_id, "QEMU", 4);
15574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
15584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->oem_id, "BOCHS ", 6);
15594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->oem_table_id, "BXPC", 4);
15604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
15614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->oem_table_id + 4, sig, 4);
15624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    h->oem_revision = cpu_to_le32(1);
15634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
15644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->asl_compiler_id, "QEMU", 4);
15654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
15664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(h->asl_compiler_id, "BXPC", 4);
15674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
15684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    h->asl_compiler_revision = cpu_to_le32(1);
15694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    h->checksum = acpi_checksum((void *)h, len);
15704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
15714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimaint acpi_build_processor_ssdt(uint8_t *ssdt)
15734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
15744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *ssdt_ptr = ssdt;
15754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i, length;
15764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus;
15774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ssdt_ptr[9] = 0; // checksum;
15794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ssdt_ptr += sizeof(struct acpi_table_header);
15804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    // caluculate the length of processor block and scope block excluding PkgLength
15824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    length = 0x0d * acpi_cpus + 4;
15834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    // build processor scope header
15854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(ssdt_ptr++) = 0x10; // ScopeOp
15864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (length <= 0x3e) {
15874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = length + 1;
15884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else {
15894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0x7F;
15904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = (length + 2) >> 6;
15914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
15924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(ssdt_ptr++) = '_'; // Name
15934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(ssdt_ptr++) = 'P';
15944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(ssdt_ptr++) = 'R';
15954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *(ssdt_ptr++) = '_';
15964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
15974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    // build object for each processor
15984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i=0;i<acpi_cpus;i++) {
15994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0x5B; // ProcessorOp
16004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0x83;
16014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0x0B; // Length
16024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 'C';  // Name (CPUxx)
16034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 'P';
16044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if ((i & 0xf0) != 0)
16054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
16064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        else
16074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *(ssdt_ptr++) = 'U';
16084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
16094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = i;
16104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0x10; // Processor block address
16114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0xb0;
16124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0;
16134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 0;
16144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *(ssdt_ptr++) = 6;    // Processor block length
16154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
16164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_build_table_header((struct acpi_table_header *)ssdt,
16184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                            "SSDT", ssdt_ptr - ssdt, 1);
16194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return ssdt_ptr - ssdt;
16214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
16224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void acpi_build_srat_memory(struct srat_memory_affinity *numamem,
16244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint64_t base, uint64_t len, int node, int enabled)
16254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
16264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->type = SRAT_MEMORY;
16274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->length = sizeof(*numamem);
16284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     memset (numamem->proximity, 0 ,4);
16294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->proximity[0] = node;
16304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->flags = cpu_to_le32(!!enabled);
16314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->base_addr_low = base & 0xFFFFFFFF;
16324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->base_addr_high = base >> 32;
16334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->length_low = len & 0xFFFFFFFF;
16344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     numamem->length_high = len >> 32;
16354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     return;
16364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
16374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* base_addr must be a multiple of 4KB */
16394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid acpi_bios_init(void)
16404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
16414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct rsdp_descriptor *rsdp;
16424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct rsdt_descriptor_rev1 *rsdt;
16434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct fadt_descriptor_rev1 *fadt;
16444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct facs_descriptor_rev1 *facs;
16454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct multiple_apic_table *madt;
16464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t *dsdt, *ssdt;
16474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
16484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct system_resource_affinity_table *srat;
16494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct acpi_20_hpet *hpet;
16504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t hpet_addr;
16514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
16524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
16534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size;
16544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t srat_addr,srat_size;
16554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t i, external_tables;
16564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int nb_numa_nodes;
16574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* reserve memory space for tables */
16594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
16604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr = align(ebda_cur_addr, 16);
16614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdp = (void *)(ebda_cur_addr);
16624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr += sizeof(*rsdp);
16634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
16644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr = align(bios_table_cur_addr, 16);
16654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdp = (void *)(bios_table_cur_addr);
16664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr += sizeof(*rsdp);
16674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
16684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
16704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    external_tables = acpi_additional_tables();
16714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
16724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    external_tables = 0;
16734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
16744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr = base_addr = ram_size - ACPI_DATA_SIZE;
16764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt_addr = addr;
16774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt = (void *)(addr);
16784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt_size = sizeof(*rsdt) + external_tables * 4;
16794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += rsdt_size;
16804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt_addr = addr;
16824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt = (void *)(addr);
16834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += sizeof(*fadt);
16844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* XXX: FACS should be in RAM */
16864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
16874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    facs_addr = addr;
16884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    facs = (void *)(addr);
16894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += sizeof(*facs);
16904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    dsdt_addr = addr;
16924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    dsdt = (void *)(addr);
16934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += sizeof(AmlCode);
16944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
16954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ssdt_addr = addr;
16964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ssdt = (void *)(addr);
16974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += acpi_build_processor_ssdt(ssdt);
16984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
16994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_select(QEMU_CFG_NUMA);
17004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    nb_numa_nodes = qemu_cfg_get64();
17014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
17024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    nb_numa_nodes = 0;
17034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
17044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (nb_numa_nodes > 0) {
17054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        addr = (addr + 7) & ~7;
17064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat_addr = addr;
17074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat_size = sizeof(*srat) +
17084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            sizeof(struct srat_processor_affinity) * smp_cpus +
17094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
17104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat = (void *)(addr);
17114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        addr += srat_size;
17124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else {
17134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat_addr = addr;
17144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat = (void*)(addr);
17154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat_size = 0;
17164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
17174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr = (addr + 7) & ~7;
17194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    madt_addr = addr;
17204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    madt_size = sizeof(*madt) +
17214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sizeof(struct madt_processor_apic) * smp_cpus +
17224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
17234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sizeof(struct madt_io_apic) + sizeof(struct madt_int_override);
17244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
17254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sizeof(struct madt_io_apic);
17264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
17274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    madt = (void *)(addr);
17284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += madt_size;
17294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
17314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr = (addr + 7) & ~7;
17324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    hpet_addr = addr;
17334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    hpet = (void *)(addr);
17344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    addr += sizeof(*hpet);
17354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
17364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* RSDP */
17384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(rsdp, 0, sizeof(*rsdp));
17394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(rsdp->signature, "RSD PTR ", 8);
17404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
17414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(rsdp->oem_id, "QEMU  ", 6);
17424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
17434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(rsdp->oem_id, "BOCHS ", 6);
17444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
17454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
17464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdp->checksum = acpi_checksum((void *)rsdp, 20);
17474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* FADT */
17494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(fadt, 0, sizeof(*fadt));
17504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->firmware_ctrl = cpu_to_le32(facs_addr);
17514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->dsdt = cpu_to_le32(dsdt_addr);
17524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->model = 1;
17534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->reserved1 = 0;
17544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->sci_int = cpu_to_le16(pm_sci_int);
17554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
17564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->acpi_enable = 0xf1;
17574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->acpi_disable = 0xf0;
17584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
17594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
17604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
17614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm1_evt_len = 4;
17624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm1_cnt_len = 2;
17634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->pm_tmr_len = 4;
17644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
17654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
17664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->gpe0_blk = cpu_to_le32(0xafe0);
17674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->gpe0_blk_len = 4;
17684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
17694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
17704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
17714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                            sizeof(*fadt), 1);
17724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* FACS */
17744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(facs, 0, sizeof(*facs));
17754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(facs->signature, "FACS", 4);
17764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    facs->length = cpu_to_le32(sizeof(*facs));
17774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("Firmware waking vector %p\n", &facs->firmware_waking_vector);
17784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* DSDT */
17804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(dsdt, AmlCode, sizeof(AmlCode));
17814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* MADT */
17834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    {
17844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct madt_processor_apic *apic;
17854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct madt_io_apic *io_apic;
17864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
17874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct madt_int_override *int_override;
17884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
17894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
17904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memset(madt, 0, madt_size);
17914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        madt->local_apic_address = cpu_to_le32(0xfee00000);
17924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        madt->flags = cpu_to_le32(1);
17934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        apic = (void *)(madt + 1);
17944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for(i=0;i<smp_cpus;i++) {
17954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic->type = APIC_PROCESSOR;
17964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic->length = sizeof(*apic);
17974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic->processor_id = i;
17984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic->local_apic_id = i;
17994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic->flags = cpu_to_le32(1);
18004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            apic++;
18014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
18024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic = (void *)apic;
18034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic->type = APIC_IO;
18044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic->length = sizeof(*io_apic);
18054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic->io_apic_id = smp_cpus;
18064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic->address = cpu_to_le32(0xfec00000);
18074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic->interrupt = cpu_to_le32(0);
18084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
18094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        io_apic++;
18104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override = (void *)io_apic;
18124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->type = APIC_XRUPT_OVERRIDE;
18134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->length = sizeof(*int_override);
18144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->bus = cpu_to_le32(0);
18154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->source = cpu_to_le32(0);
18164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->gsi = cpu_to_le32(2);
18174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int_override->flags = cpu_to_le32(0);
18184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
18194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        acpi_build_table_header((struct acpi_table_header *)madt,
18214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                "APIC", madt_size, 1);
18224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
18234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(rsdt, 0, rsdt_size);
18254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
18264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* SRAT */
18274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (nb_numa_nodes > 0) {
18284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct srat_processor_affinity *core;
18294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct srat_memory_affinity *numamem;
18304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int slots;
18314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint64_t mem_len, mem_base, next_base = 0, curnode;
18324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_select(QEMU_CFG_NUMA);
18344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_get64();
18354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memset (srat, 0 , srat_size);
18364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        srat->reserved1=1;
18374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        core = (void*)(srat + 1);
18394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for (i = 0; i < smp_cpus; ++i) {
18404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core->type = SRAT_PROCESSOR;
18414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core->length = sizeof(*core);
18424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core->local_apic_id = i;
18434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             curnode = qemu_cfg_get64();
18444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core->proximity_lo = curnode;
18454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             memset (core->proximity_hi, 0, 3);
18464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core->local_sapic_eid = 0;
18474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             if (i < smp_cpus)
18484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                 core->flags = cpu_to_le32(1);
18494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             else
18504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                 core->flags = 0;
18514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima             core++;
18524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
18534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* the memory map is a bit tricky, it contains at least one hole
18554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima         * from 640k-1M and possibly another one from 3.5G-4G.
18564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima         */
18574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        numamem = (void*)core; slots = 0;
18584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
18594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        next_base = 1024 * 1024; numamem++;slots++;
18604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for (i = 1; i < nb_numa_nodes + 1; ++i) {
18614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            mem_base = next_base;
18624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            mem_len = qemu_cfg_get64();
18634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (i == 1) mem_len -= 1024 * 1024;
18644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            next_base = mem_base + mem_len;
18654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            /* Cut out the PCI hole */
18674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            if (mem_base <= ram_size && next_base > ram_size) {
18684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                mem_len -= next_base - ram_size;
18694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                if (mem_len > 0) {
18704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
18714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                    numamem++; slots++;
18724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                }
18734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                mem_base = 1ULL << 32;
18744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                mem_len = next_base - ram_size;
18754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                next_base += (1ULL << 32) - ram_size;
18764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            }
18774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
18784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            numamem++; slots++;
18794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
18804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        for (; slots < nb_numa_nodes + 2; slots++) {
18814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            acpi_build_srat_memory(numamem, 0, 0, 0, 0);
18824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            numamem++;
18834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
18844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima         acpi_build_table_header((struct acpi_table_header *)srat,
18864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                "SRAT", srat_size, 1);
18874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
18884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* HPET */
18904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(hpet, 0, sizeof(*hpet));
18914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Note timer_block_id value must be kept in sync with value advertised by
18924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     * emulated hpet
18934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima     */
18944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    hpet->timer_block_id = cpu_to_le32(0x8086a201);
18954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
18964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_build_table_header((struct  acpi_table_header *)hpet,
18974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                             "HPET", sizeof(*hpet), 1);
18984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
18994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_additional_tables(); /* resets cfg to required entry */
19004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for(i = 0; i < external_tables; i++) {
19014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint16_t len;
19024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if(acpi_load_table(i, addr, &len) < 0)
19034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_PANIC("Failed to load ACPI table from QEMU\n");
19044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        rsdt->table_offset_entry[i+4] = cpu_to_le32(addr);
19054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        addr += len;
19064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if(addr >= ram_size)
19074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_PANIC("ACPI table overflow\n");
19084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
19094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
19104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* RSDT */
19124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
19134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
19144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
19154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
19164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
19174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (nb_numa_nodes > 0)
19184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        rsdt->table_offset_entry[4] = cpu_to_le32(srat_addr);
19194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
19204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_build_table_header((struct acpi_table_header *)rsdt, "RSDT",
19214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        rsdt_size - (nb_numa_nodes > 0? 0: sizeof(uint32_t)), 1);
19224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    acpi_tables_size = addr - base_addr;
19244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
19264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (unsigned long)rsdp,
19274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (unsigned long)rsdt, acpi_tables_size);
19284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
19304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS entry point -- must be written to a 16-bit aligned address
19324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima   between 0xf0000 and 0xfffff.
19334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
19344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_entry_point {
19354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	char anchor_string[4];
19364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t checksum;
19374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t length;
19384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t smbios_major_version;
19394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t smbios_minor_version;
19404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t max_structure_size;
19414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t entry_point_revision;
19424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t formatted_area[5];
19434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	char intermediate_anchor_string[5];
19444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t intermediate_checksum;
19454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t structure_table_length;
19464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t structure_table_address;
19474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t number_of_structures;
19484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t smbios_bcd_revision;
19494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
19504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* This goes at the beginning of every SMBIOS structure. */
19524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_structure_header {
19534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t type;
19544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t length;
19554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t handle;
19564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
19574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 0 - BIOS Information */
19594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_0 {
19604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
19614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t vendor_str;
19624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bios_version_str;
19634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t bios_starting_address_segment;
19644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bios_release_date_str;
19654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bios_rom_size;
19664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bios_characteristics[8];
19674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bios_characteristics_extension_bytes[2];
19684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t system_bios_major_release;
19694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t system_bios_minor_release;
19704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t embedded_controller_major_release;
19714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t embedded_controller_minor_release;
19724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
19734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 1 - System Information */
19754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_1 {
19764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
19774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t manufacturer_str;
19784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t product_name_str;
19794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t version_str;
19804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t serial_number_str;
19814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t uuid[16];
19824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t wake_up_type;
19834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t sku_number_str;
19844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t family_str;
19854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
19864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
19874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 3 - System Enclosure (v2.3) */
19884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_3 {
19894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
19904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t manufacturer_str;
19914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t type;
19924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t version_str;
19934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t serial_number_str;
19944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t asset_tag_number_str;
19954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t boot_up_state;
19964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t power_supply_state;
19974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t thermal_state;
19984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t security_status;
19994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint32_t oem_defined;
20004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t height;
20014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t number_of_power_cords;
20024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t contained_element_count;
20034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    // contained elements follow
20044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 4 - Processor Information (v2.0) */
20074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_4 {
20084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t socket_designation_str;
20104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t processor_type;
20114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t processor_family;
20124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t processor_manufacturer_str;
20134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t processor_id[2];
20144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t processor_version_str;
20154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t voltage;
20164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t external_clock;
20174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t max_speed;
20184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t current_speed;
20194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t status;
20204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t processor_upgrade;
20214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint16_t l1_cache_handle;
20224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint16_t l2_cache_handle;
20234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint16_t l3_cache_handle;
20244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 16 - Physical Memory Array
20274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *   Associated with one type 17 (Memory Device).
20284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
20294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_16 {
20304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t location;
20324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t use;
20334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t error_correction;
20344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t maximum_capacity;
20354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t memory_error_information_handle;
20364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t number_of_memory_devices;
20374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 17 - Memory Device
20404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima *   Associated with one type 19
20414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima */
20424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_17 {
20434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t physical_memory_array_handle;
20454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t memory_error_information_handle;
20464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t total_width;
20474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t data_width;
20484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t size;
20494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t form_factor;
20504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t device_set;
20514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t device_locator_str;
20524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t bank_locator_str;
20534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t memory_type;
20544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t type_detail;
20554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 19 - Memory Array Mapped Address */
20584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_19 {
20594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t starting_address;
20614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t ending_address;
20624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t memory_array_handle;
20634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t partition_width;
20644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 20 - Memory Device Mapped Address */
20674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_20 {
20684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t starting_address;
20704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint32_t ending_address;
20714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t memory_device_handle;
20724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint16_t memory_array_mapped_address_handle;
20734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t partition_row_position;
20744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t interleave_position;
20754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t interleaved_data_depth;
20764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 32 - System Boot Information */
20794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_32 {
20804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t reserved[6];
20824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	uint8_t boot_status;
20834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* SMBIOS type 127 -- End-of-table */
20864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_type_127 {
20874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	struct smbios_structure_header header;
20884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
20894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
20904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void
20914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_entry_point_init(void *start,
20924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                        uint16_t max_structure_size,
20934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                        uint16_t structure_table_length,
20944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                        uint32_t structure_table_address,
20954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                        uint16_t number_of_structures)
20964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
20974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t sum;
20984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i;
20994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
21004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(ep->anchor_string, "_SM_", 4);
21024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->length = 0x1f;
21034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->smbios_major_version = 2;
21044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->smbios_minor_version = 4;
21054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->max_structure_size = max_structure_size;
21064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->entry_point_revision = 0;
21074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(ep->formatted_area, 0, 5);
21084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
21094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->structure_table_length = structure_table_length;
21114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->structure_table_address = structure_table_address;
21124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->number_of_structures = number_of_structures;
21134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->smbios_bcd_revision = 0x24;
21144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->checksum = 0;
21164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->intermediate_checksum = 0;
21174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    sum = 0;
21194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0; i < 0x10; i++)
21204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sum += ((int8_t *)start)[i];
21214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->checksum = -sum;
21224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    sum = 0;
21244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0x10; i < ep->length; i++)
21254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        sum += ((int8_t *)start)[i];
21264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ep->intermediate_checksum = -sum;
21274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
21284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_header {
21304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t length;
21314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t type;
21324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
21334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_field {
21354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_header header;
21364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t type;
21374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t offset;
21384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t data[];
21394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
21404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastruct smbios_table {
21424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_header header;
21434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint8_t data[];
21444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} __attribute__((__packed__));
21454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define SMBIOS_FIELD_ENTRY 0
21474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define SMBIOS_TABLE_ENTRY 1
21484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic size_t
21504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_load_field(int type, size_t offset, void *addr)
21514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
21524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
21534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i;
21544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = smbios_entries(); i > 0; i--) {
21564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct smbios_field field;
21574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read((uint8_t *)&field, sizeof(struct smbios_header));
21594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        field.header.length -= sizeof(struct smbios_header);
21604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (field.header.type != SMBIOS_FIELD_ENTRY) {
21624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            while (field.header.length--)
21634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                inb(QEMU_CFG_DATA_PORT);
21644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            continue;
21654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
21664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read((uint8_t *)&field.type,
21684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                      sizeof(field) - sizeof(struct smbios_header));
21694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        field.header.length -= sizeof(field) - sizeof(struct smbios_header);
21704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (field.type != type || field.offset != offset) {
21724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            while (field.header.length--)
21734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                inb(QEMU_CFG_DATA_PORT);
21744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            continue;
21754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
21764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read(addr, field.header.length);
21784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return (size_t)field.header.length;
21794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
21804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
21814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 0;
21824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
21834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define load_str_field_with_default(type, field, def) do {             \
21854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
21864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                            field), end);              \
21874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (size > 0) {                                                    \
21884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        end += size;                                                   \
21894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else {                                                           \
21904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memcpy(end, def, sizeof(def));                                 \
21914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        end += sizeof(def);                                            \
21924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }                                                                  \
21934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->field = ++str_index;                                            \
21944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} while (0)
21954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
21964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define load_str_field_or_skip(type, field) do {                       \
21974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
21984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                            field), end);              \
21994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (size > 0) {                                                    \
22004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        end += size;                                                   \
22014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        p->field = ++str_index;                                        \
22024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    } else {                                                           \
22034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        p->field = 0;                                                  \
22044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }                                                                  \
22054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} while (0)
22064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 0 -- BIOS Information */
22084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define RELEASE_DATE_STR "01/01/2007"
22094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
22104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_0(void *start)
22114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
22124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_0 *p = (struct smbios_type_0 *)start;
22134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *end = (char *)start + sizeof(struct smbios_type_0);
22144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    size_t size;
22154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int str_index = 0;
22164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 0;
22184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_0);
22194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0;
22204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_with_default(0, vendor_str, BX_APPNAME);
22224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_with_default(0, bios_version_str, BX_APPNAME);
22234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bios_starting_address_segment = 0xe800;
22254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
22274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bios_rom_size = 0; /* FIXME */
22294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(p->bios_characteristics, 0, 8);
22314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
22324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bios_characteristics_extension_bytes[0] = 0;
22334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bios_characteristics_extension_bytes[1] = 0;
22344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!smbios_load_field(0, offsetof(struct smbios_type_0,
22364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                       system_bios_major_release),
22374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                           &p->system_bios_major_release))
22384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        p->system_bios_major_release = 1;
22394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!smbios_load_field(0, offsetof(struct smbios_type_0,
22414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                       system_bios_minor_release),
22424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                           &p->system_bios_minor_release))
22434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        p->system_bios_minor_release = 0;
22444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->embedded_controller_major_release = 0xff;
22464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->embedded_controller_minor_release = 0xff;
22474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *end = 0;
22494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    end++;
22504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return end;
22524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
22534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 1 -- System Information */
22554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
22564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_1(void *start)
22574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
22584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_1 *p = (struct smbios_type_1 *)start;
22594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *end = (char *)start + sizeof(struct smbios_type_1);
22604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    size_t size;
22614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int str_index = 0;
22624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 1;
22644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_1);
22654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x100;
22664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, manufacturer_str);
22684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, product_name_str);
22694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, version_str);
22704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, serial_number_str);
22714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    size = smbios_load_field(1, offsetof(struct smbios_type_1,
22734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                         uuid), &p->uuid);
22744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (size == 0)
22754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        memset(p->uuid, 0, 16);
22764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->wake_up_type = 0x06; /* power switch */
22784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, sku_number_str);
22804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    load_str_field_or_skip(1, family_str);
22814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *end = 0;
22834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    end++;
22844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!str_index) {
22854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *end = 0;
22864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        end++;
22874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
22884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return end;
22904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
22914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 3 -- System Enclosure */
22934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
22944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_3(void *start)
22954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
22964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_3 *p = (struct smbios_type_3 *)start;
22974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
22984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 3;
22994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_3);
23004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x300;
23014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->manufacturer_str = 0;
23034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->type = 0x01; /* other */
23044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->version_str = 0;
23054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->serial_number_str = 0;
23064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->asset_tag_number_str = 0;
23074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->boot_up_state = 0x03; /* safe */
23084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->power_supply_state = 0x03; /* safe */
23094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->thermal_state = 0x03; /* safe */
23104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->security_status = 0x02; /* unknown */
23114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->oem_defined = 0;
23124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->height = 0;
23134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->number_of_power_cords = 0;
23144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->contained_element_count = 0;
23154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_3);
23174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
23184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start+2;
23204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
23214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 4 -- Processor Information */
23234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
23244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_4(void *start, unsigned int cpu_number)
23254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
23264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_4 *p = (struct smbios_type_4 *)start;
23274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 4;
23294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_4);
23304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x400 + cpu_number;
23314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->socket_designation_str = 1;
23334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_type = 0x03; /* CPU */
23344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_family = 0x01; /* other */
23354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_manufacturer_str = 0;
23364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_id[0] = cpuid_signature;
23384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_id[1] = cpuid_features;
23394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_version_str = 0;
23414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->voltage = 0;
23424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->external_clock = 0;
23434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->max_speed = 0; /* unknown */
23454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->current_speed = 0; /* unknown */
23464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->status = 0x41; /* socket populated, CPU enabled */
23484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->processor_upgrade = 0x01; /* other */
23494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->l1_cache_handle = 0xffff; /* cache information structure not provided */
23514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->l2_cache_handle = 0xffff;
23524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->l3_cache_handle = 0xffff;
23534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_4);
23554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memcpy((char *)start, "CPU  " "\0" "" "\0" "", 7);
23574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	((char *)start)[4] = cpu_number + '0';
23584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start+7;
23604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
23614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 16 -- Physical Memory Array */
23634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
23644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_16(void *start, uint32_t memsize, int nr_mem_devs)
23654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
23664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_16 *p = (struct smbios_type_16*)start;
23674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 16;
23694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_16);
23704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x1000;
23714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->location = 0x01; /* other */
23734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->use = 0x03; /* system memory */
23744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->error_correction = 0x01; /* other */
23754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->maximum_capacity = memsize * 1024;
23764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->memory_error_information_handle = 0xfffe; /* none provided */
23774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->number_of_memory_devices = nr_mem_devs;
23784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_16);
23804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
23814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start + 2;
23834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
23844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 17 -- Memory Device */
23864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
23874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_17(void *start, uint32_t memory_size_mb, int instance)
23884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
23894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_17 *p = (struct smbios_type_17 *)start;
23904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 17;
23924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_17);
23934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x1100 + instance;
23944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
23954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->physical_memory_array_handle = 0x1000;
23964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->total_width = 64;
23974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->data_width = 64;
23984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* TODO: should assert in case something is wrong   ASSERT((memory_size_mb & ~0x7fff) == 0); */
23994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->size = memory_size_mb;
24004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->form_factor = 0x09; /* DIMM */
24014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->device_set = 0;
24024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->device_locator_str = 1;
24034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->bank_locator_str = 0;
24044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->memory_type = 0x07; /* RAM */
24054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->type_detail = 0;
24064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_17);
24084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    snprintf(start, 8, "DIMM %d", instance);
24094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += strlen(start) + 1;
24104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint8_t *)start) = 0;
24114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start+1;
24134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
24144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 19 -- Memory Array Mapped Address */
24164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
24174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_19(void *start, uint32_t memory_size_mb, int instance)
24184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
24194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_19 *p = (struct smbios_type_19 *)start;
24204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 19;
24224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_19);
24234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x1300 + instance;
24244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->starting_address = instance << 24;
24264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
24274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->memory_array_handle = 0x1000;
24284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->partition_width = 1;
24294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_19);
24314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
24324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start + 2;
24344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
24354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 20 -- Memory Device Mapped Address */
24374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
24384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_20(void *start, uint32_t memory_size_mb, int instance)
24394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
24404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_20 *p = (struct smbios_type_20 *)start;
24414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 20;
24434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_20);
24444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x1400 + instance;
24454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->starting_address = instance << 24;
24474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
24484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->memory_device_handle = 0x1100 + instance;
24494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->memory_array_mapped_address_handle = 0x1300 + instance;
24504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->partition_row_position = 1;
24514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->interleave_position = 0;
24524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->interleaved_data_depth = 0;
24534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_20);
24554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
24574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start+2;
24584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
24594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 32 -- System Boot Information */
24614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
24624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_32(void *start)
24634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
24644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_32 *p = (struct smbios_type_32 *)start;
24654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 32;
24674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_32);
24684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x2000;
24694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    memset(p->reserved, 0, 6);
24704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->boot_status = 0; /* no errors detected */
24714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_32);
24734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
24744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start+2;
24764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
24774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima/* Type 127 -- End of Table */
24794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void *
24804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_init_type_127(void *start)
24814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
24824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    struct smbios_type_127 *p = (struct smbios_type_127 *)start;
24834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.type = 127;
24854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.length = sizeof(struct smbios_type_127);
24864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    p->header.handle = 0x7f00;
24874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start += sizeof(struct smbios_type_127);
24894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    *((uint16_t *)start) = 0;
24904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return start + 2;
24924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
24934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
24944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic int
24954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimasmbios_load_external(int type, char **p, unsigned *nr_structs,
24964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                     unsigned *max_struct_size)
24974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
24984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
24994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    static uint64_t used_bitmap[4] = { 0 };
25004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *start = *p;
25014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i;
25024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Check if we've already reported these tables */
25044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
25054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return 1;
25064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Don't introduce spurious end markers */
25084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (type == 127)
25094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return 0;
25104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = smbios_entries(); i > 0; i--) {
25124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct smbios_table table;
25134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        struct smbios_structure_header *header = (void *)*p;
25144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        int string;
25154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read((uint8_t *)&table, sizeof(struct smbios_header));
25174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        table.header.length -= sizeof(struct smbios_header);
25184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (table.header.type != SMBIOS_TABLE_ENTRY) {
25204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            while (table.header.length--)
25214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                inb(QEMU_CFG_DATA_PORT);
25224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            continue;
25234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
25244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read((uint8_t *)*p, sizeof(struct smbios_structure_header));
25264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        table.header.length -= sizeof(struct smbios_structure_header);
25274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (header->type != type) {
25294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            while (table.header.length--)
25304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                inb(QEMU_CFG_DATA_PORT);
25314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            continue;
25324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
25334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *p += sizeof(struct smbios_structure_header);
25354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* Entries end with a double NULL char, if there's a string at
25374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima         * the end (length is greater than formatted length), the string
25384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima         * terminator provides the first NULL. */
25394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        string = header->length < table.header.length +
25404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                 sizeof(struct smbios_structure_header);
25414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* Read the rest and terminate the entry */
25434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        qemu_cfg_read((uint8_t *)*p, table.header.length);
25444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *p += table.header.length;
25454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *((uint8_t*)*p) = 0;
25464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        (*p)++;
25474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (!string) {
25484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *((uint8_t*)*p) = 0;
25494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            (*p)++;
25504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
25514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        (*nr_structs)++;
25534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (*p - (char *)header > *max_struct_size)
25544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            *max_struct_size = *p - (char *)header;
25554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
25564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Mark that we've reported on this type */
25584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
25594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return (start != *p);
25614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else /* !BX_QEMU */
25624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 0;
25634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
25644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
25654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid smbios_init(void)
25674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
25684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
25694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    char *start, *p, *q;
25704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
25714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                  (ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
25724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    int i, nr_mem_devs;
25734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
25754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr = align(ebda_cur_addr, 16);
25764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start = (void *)(ebda_cur_addr);
25774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
25784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr = align(bios_table_cur_addr, 16);
25794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start = (void *)(bios_table_cur_addr);
25804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
25814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima	p = (char *)start + sizeof(struct smbios_entry_point);
25834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#define add_struct(type, args...) do {                                    \
25854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (!smbios_load_external(type, &p, &nr_structs, &max_struct_size)) { \
25864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        q = smbios_init_type_##type(args);                                \
25874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        nr_structs++;                                                     \
25884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if ((q - p) > max_struct_size)                                    \
25894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            max_struct_size = q - p;                                      \
25904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        p = q;                                                            \
25914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }                                                                     \
25924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima} while (0)
25934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
25944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(0, p);
25954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(1, p);
25964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(3, p);
25974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
25984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        add_struct(4, p, cpu_num);
25994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Each 'memory device' covers up to 16GB of address space. */
26014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    nr_mem_devs = (memsize + 0x3fff) >> 14;
26024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(16, p, memsize, nr_mem_devs);
26034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for ( i = 0; i < nr_mem_devs; i++ )
26044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    {
26054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
26064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima                                ? (((memsize-1) & 0x3fff)+1) : 0x4000);
26074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        add_struct(17, p, dev_memsize, i);
26084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        add_struct(19, p, dev_memsize, i);
26094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        add_struct(20, p, dev_memsize, i);
26104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
26114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(32, p);
26134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    /* Add any remaining provided entries before the end marker */
26144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (i = 0; i < 256; i++)
26154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        smbios_load_external(i, &p, &nr_structs, &max_struct_size);
26164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    add_struct(127, p);
26174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#undef add_struct
26194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    smbios_entry_point_init(
26214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        start, max_struct_size,
26224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        (p - (char *)start) - sizeof(struct smbios_entry_point),
26234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        (uint32_t)(start + sizeof(struct smbios_entry_point)),
26244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        nr_structs);
26254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
26274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ebda_cur_addr += (p - (char *)start);
26284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
26294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    bios_table_cur_addr += (p - (char *)start);
26304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
26314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start);
26334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
26344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic uint32_t find_resume_vector(void)
26364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
26374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    unsigned long addr, start, end;
26384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
26404d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start = align(ebda_cur_addr, 16);
26414d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    end = 0xa000 << 4;
26424d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#else
26434d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (bios_table_cur_addr == 0)
26444d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return 0;
26454d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    start = align(bios_table_cur_addr, 16);
26464d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    end = bios_table_end_addr;
26474d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
26484d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26494d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    for (addr = start; addr < end; addr += 16) {
26504d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (!memcmp((void*)addr, "RSD PTR ", 8)) {
26514d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            struct rsdp_descriptor *rsdp = (void*)addr;
26524d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            struct rsdt_descriptor_rev1 *rsdt = (void*)rsdp->rsdt_physical_address;
26534d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[0];
26544d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
26554d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            return facs->firmware_waking_vector;
26564d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
26574d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
26584d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26594d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    return 0;
26604d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
26614d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26624d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void find_440fx(PCIDevice *d)
26634d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
26644d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t vendor_id, device_id;
26654d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26664d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
26674d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    device_id = pci_config_readw(d, PCI_DEVICE_ID);
26684d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26694d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441)
26704d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        i440_pcidev = *d;
26714d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
26724d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26734d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimastatic void reinit_piix4_pm(PCIDevice *d)
26744d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
26754d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    uint16_t vendor_id, device_id;
26764d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26774d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
26784d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    device_id = pci_config_readw(d, PCI_DEVICE_ID);
26794d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26804d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3)
26814d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        piix4_pm_enable(d);
26824d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
26834d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26844d07f569799aaae0d7fccf8e76386d450664987fJun Nakajimavoid rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag)
26854d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima{
26864d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("Starting rombios32\n");
26874d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    BX_INFO("Shutdown flag %x\n", *shutdown_flag);
26884d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26894d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_QEMU
26904d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    qemu_cfg_port = qemu_cfg_port_probe();
26914d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
26924d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26934d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    ram_probe();
26944d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26954d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    cpu_probe();
26964d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26974d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    setup_mtrr();
26984d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
26994d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    smp_probe();
27004d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27014d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    find_bios_table_area();
27024d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27034d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (*shutdown_flag == 0xfe) {
27044d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        /* redirect bios read access to RAM */
27054d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        pci_for_each_device(find_440fx);
27064d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        bios_lock_shadow_ram(); /* bios is already copied */
27074d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        *s3_resume_vector = find_resume_vector();
27084d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (!*s3_resume_vector) {
27094d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_INFO("This is S3 resume but wakeup vector is NULL\n");
27104d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        } else {
27114d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_INFO("S3 resume vector %p\n", *s3_resume_vector);
27124d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            pci_for_each_device(reinit_piix4_pm);
27134d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        }
27144d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        return;
27154d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
27164d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27174d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    pci_bios_init();
27184d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27194d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    if (bios_table_cur_addr != 0) {
27204d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27214d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        mptable_init();
27224d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27234d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        smbios_init();
27244d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27254d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (acpi_enabled)
27264d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            acpi_bios_init();
27274d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27284d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        bios_lock_shadow_ram();
27294d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima
27304d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr);
27314d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (bios_table_cur_addr > bios_table_end_addr)
27324d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_PANIC("bios_table_end_addr overflow!\n");
27334d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#ifdef BX_USE_EBDA_TABLES
27344d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
27354d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima        if (ebda_cur_addr > 0xA0000)
27364d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima            BX_PANIC("ebda_cur_addr overflow!\n");
27374d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima#endif
27384d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima    }
27394d07f569799aaae0d7fccf8e76386d450664987fJun Nakajima}
2740