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>
37 u32 VSA_vrRead(u16 classIndex);
38 void do_vsmbios(void);
40 #define VSA2_BUFFER 0x60000
41 #define VSA2_ENTRY_POINT 0x60020
42 #define VSA2_SIGNATURE 0x56534132 // 'VSA2' returned in EAX
43 #define SIGNATURE 0x03
47 * The address arguments to this function are PHYSICAL ADDRESSES!
52 static void real_mode_switch_call_vsm(unsigned long smm, unsigned long sysm)
54 u16 entryHi = (VSA2_ENTRY_POINT & 0xffff0000) >> 4;
55 u16 entryLo = (VSA2_ENTRY_POINT & 0xffff);
58 /* Paranoia -- does ecx get saved? not sure. This is
59 * the easiest safe thing to do.
63 " mov %%esp, __stack \n"
67 /* Get devfn into %%ecx. */
68 " movl %%esp, %%ebp \n"
69 /* Get the smm and sysm args into ecx and edx. */
73 " lgdt %%cs:__mygdtaddr \n"
74 /* This configures CS properly for real mode. */
75 " ljmp $0x28, $__rms_16bit\n"
78 /* 16 bit code from here on... */
79 /* Load the segment registers with properly configured segment
80 * descriptors. They will retain these configurations (limits,
81 * writability, etc.) once protected mode is turned off.
89 /* Turn off protection (bit 0 in CR0). */
90 " movl %%cr0, %%eax \n"
91 " andl $0xFFFFFFFE, %%eax \n"
92 " movl %%eax, %%cr0 \n"
93 /* Now really going into real mode. */
94 " ljmp $0, $__rms_real\n"
97 /* Put the stack at the end of page zero.
98 * That way we can easily share it between real and protected,
99 * since the 16-bit ESP at segment 0 will work for any case.
105 " movl $0x1000, %%eax \n"
106 " movl %%eax, %%esp \n"
107 /* Dump zeros in the other segregs. */
109 /* FIXME: Big real mode for gs, fs? */
112 " mov $0x40, %%ax \n"
114 /* " mov %%cx, %%ax \n" */
117 /* Call the VSA2 entry point address. */
119 /* If we got here, just about done.
120 * Need to get back to protected mode.
122 " movl %%cr0, %%eax \n"
123 " orl $0x0000001, %%eax\n" /* PE = 1 */
124 " movl %%eax, %%cr0 \n"
125 /* Now that we are in protected mode,
126 * jump to a 32 bit code segment.
128 " data32 ljmp $0x10, $vsmrestart\n"
131 " movw $0x18, %%ax \n"
137 /* Restore proper gdt. */
138 " lgdt %%cs:gdtarg \n"
141 " mov __stack, %%esp \n"
143 "g" (smm), "g"(sysm), "g"(entryHi), "g"(entryLo)
147 __asm__(".text\n" "real_mode_switch_end:\n");
148 extern char real_mode_switch_end[];
150 /* andrei: Some VSA virtual register helpers: raw read and MSR read. */
152 u32 VSA_vrRead(u16 classIndex)
154 unsigned eax, ebx, ecx, edx;
156 "movw $0x0AC1C, %%dx \n"
157 "orl $0x0FC530000, %%eax \n"
158 "outl %%eax, %%dx \n"
161 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
168 u32 VSA_msrRead(u32 msrAddr)
170 unsigned eax, ebx, ecx, edx;
172 "movw $0x0AC1C, %%dx \n"
173 "movl $0x0FC530007, %%eax \n"
174 "outl %%eax, %%dx \n"
177 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
184 void do_vsmbios(void)
189 printk_err( "do_vsmbios\n");
190 /* Clear VSM BIOS data area. */
191 for (i = 0x400; i < 0x500; i++)
192 *(volatile unsigned char *)i = 0;
193 /* set up cbfs and find the vsa file -- later */
195 init_archive(&archive);
197 if (find_file(&archive, "blob/vsa", &file))
198 die("FATAL: NO VSA found!\n");
200 if (process_file(&file, (void *)VSA2_BUFFER))
201 die("FATAL: Processing /blob/vsa failed\n");
204 buf = (unsigned char *)VSA2_BUFFER;
205 printk_debug("buf[0x20] signature is %x:%x:%x:%x\n",
206 buf[0x20], buf[0x21], buf[0x22], buf[0x23]);
207 /* Check for POST code at start of vsainit.bin. If you don't see it,
210 if ((buf[0x20] != 0xb0) || (buf[0x21] != 0x10) ||
211 (buf[0x22] != 0xe6) || (buf[0x23] != 0x80)) {
212 die("FATAL: no vsainit.bin signature, skipping!\n");
215 /* ecx gets smm, edx gets sysm. */
216 printk_err("Call real_mode_switch_call_vsm\n");
217 // real_mode_switch_call_vsm(MSR_GLIU0_SMM, MSR_GLIU0_SYSMEM);
219 /* Restart Timer 1. */
223 /* Check that VSA is running OK. */
224 if (VSA_vrRead(SIGNATURE) == VSA2_SIGNATURE)
225 printk_debug("do_vsmbios: VSA2 VR signature verified\n");
227 die("FATAL: VSA2 VR signature not valid, install failed!\n");