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