2 * This file is part of the coreboot project.
4 * Copyright (C) 2000 Erik Arjan Hendriks
5 * Copyright (C) 2000 Scyld Computing Corporation
6 * Copyright (C) 2001 University of California. LA-CC Number 01-67.
7 * Copyright (C) 2005 Nick.Barker9@btinternet.com
8 * Copyright (C) 2007 coresystems GmbH
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
24 * LA-CC is the Los Alamos Control and Compliance Number, see also:
25 * http://supply.lanl.gov/property/customs/eximguide/default.shtml
28 #include <console/console.h>
29 #include <device/device.h>
30 #include <device/pci.h>
33 #include <cpu/x86/lapic.h>
34 #include <cpu/x86/cache.h>
38 u32 VSA_vrRead(u16 classIndex);
39 void do_vsmbios(void);
41 #define VSA2_BUFFER 0x60000
42 #define VSA2_ENTRY_POINT 0x60020
43 #define VSA2_SIGNATURE 0x56534132 // 'VSA2' returned in EAX
44 #define SIGNATURE 0x03
48 * The address arguments to this function are PHYSICAL ADDRESSES!
53 static void real_mode_switch_call_vsm(unsigned long smm, unsigned long sysm)
55 u16 entryHi = (VSA2_ENTRY_POINT & 0xffff0000) >> 4;
56 u16 entryLo = (VSA2_ENTRY_POINT & 0xffff);
59 /* Paranoia -- does ecx get saved? not sure. This is
60 * the easiest safe thing to do.
64 " mov %%esp, __stack \n"
68 /* Get devfn into %%ecx. */
69 " movl %%esp, %%ebp \n"
70 /* Get the smm and sysm args into ecx and edx. */
74 " lgdt %%cs:__mygdtaddr \n"
75 /* This configures CS properly for real mode. */
76 " ljmp $0x28, $__rms_16bit\n"
79 /* 16 bit code from here on... */
80 /* Load the segment registers with properly configured segment
81 * descriptors. They will retain these configurations (limits,
82 * writability, etc.) once protected mode is turned off.
90 /* Turn off protection (bit 0 in CR0). */
91 " movl %%cr0, %%eax \n"
92 " andl $0xFFFFFFFE, %%eax \n"
93 " movl %%eax, %%cr0 \n"
94 /* Now really going into real mode. */
95 " ljmp $0, $__rms_real\n"
98 /* Put the stack at the end of page zero.
99 * That way we can easily share it between real and protected,
100 * since the 16-bit ESP at segment 0 will work for any case.
106 " movl $0x1000, %%eax \n"
107 " movl %%eax, %%esp \n"
108 /* Dump zeros in the other segregs. */
110 /* FIXME: Big real mode for gs, fs? */
113 " mov $0x40, %%ax \n"
115 /* " mov %%cx, %%ax \n" */
118 /* Call the VSA2 entry point address. */
120 /* If we got here, just about done.
121 * Need to get back to protected mode.
123 " movl %%cr0, %%eax \n"
124 " orl $0x0000001, %%eax\n" /* PE = 1 */
125 " movl %%eax, %%cr0 \n"
126 /* Now that we are in protected mode,
127 * jump to a 32 bit code segment.
129 " data32 ljmp $0x10, $vsmrestart\n"
132 " movw $0x18, %%ax \n"
138 /* Restore proper gdt. */
139 " lgdt %%cs:gdtarg \n"
142 " mov __stack, %%esp \n"
144 "g" (smm), "g"(sysm), "g"(entryHi), "g"(entryLo)
148 __asm__(".text\n" "real_mode_switch_end:\n");
149 extern char real_mode_switch_end[];
151 /* andrei: Some VSA virtual register helpers: raw read and MSR read. */
153 u32 VSA_vrRead(u16 classIndex)
155 unsigned eax, ebx, ecx, edx;
157 "movw $0x0AC1C, %%dx \n"
158 "orl $0x0FC530000, %%eax \n"
159 "outl %%eax, %%dx \n"
162 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
169 u32 VSA_msrRead(u32 msrAddr)
171 unsigned eax, ebx, ecx, edx;
173 "movw $0x0AC1C, %%dx \n"
174 "movl $0x0FC530007, %%eax \n"
175 "outl %%eax, %%dx \n"
178 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
185 void do_vsmbios(void)
190 printk_err( "do_vsmbios\n");
191 /* Clear VSM BIOS data area. */
192 for (i = 0x400; i < 0x500; i++)
193 *(volatile unsigned char *)i = 0;
194 if ((unsigned int)cbfs_load_stage("vsa") != VSA2_ENTRY_POINT) {
195 printk_err("do_vsmbios: Failed to load VSA.\n");
199 printk_debug("buf[0x20] signature is %x:%x:%x:%x\n",
200 buf[0x20], buf[0x21], buf[0x22], buf[0x23]);
201 /* Check for POST code at start of vsainit.bin. If you don't see it,
204 if ((buf[0x20] != 0xb0) || (buf[0x21] != 0x10) ||
205 (buf[0x22] != 0xe6) || (buf[0x23] != 0x80)) {
206 die("FATAL: no vsainit.bin signature, skipping!\n");
209 /* ecx gets smm, edx gets sysm. */
210 printk_err("Call real_mode_switch_call_vsm\n");
211 // real_mode_switch_call_vsm(MSR_GLIU0_SMM, MSR_GLIU0_SYSMEM);
213 /* Restart Timer 1. */
217 /* Check that VSA is running OK. */
218 if (VSA_vrRead(SIGNATURE) == VSA2_SIGNATURE)
219 printk_debug("do_vsmbios: VSA2 VR signature verified\n");
221 die("FATAL: VSA2 VR signature not valid, install failed!\n");