fix some wrong versions of the FSF's address (trivial)
[coreboot.git] / src / cpu / amd / model_gx2 / vsmsetup.c
1 /*
2  * This file is part of the coreboot project.
3  *
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
9  *
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.
14  *
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.
19  *
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.
23  *
24  * LA-CC is the Los Alamos Control and Compliance Number, see also:
25  * http://supply.lanl.gov/property/customs/eximguide/default.shtml
26  */
27
28 #include <console/console.h>
29 #include <device/device.h>
30 #include <device/pci.h>
31 #include <string.h>
32 #include <cpu/cpu.h>
33 #include <cpu/x86/lapic.h>
34 #include <cpu/x86/cache.h>
35 #include <arch/io.h>
36
37 u32 VSA_vrRead(u16 classIndex);
38 void do_vsmbios(void);
39
40 #define VSA2_BUFFER             0x60000
41 #define VSA2_ENTRY_POINT        0x60020
42 #define VSA2_SIGNATURE  0x56534132      // 'VSA2' returned in EAX 
43 #define SIGNATURE                       0x03
44 /**
45  * TODO.
46  *
47  * The address arguments to this function are PHYSICAL ADDRESSES!
48  *
49  * @param smm TODO.
50  * @param sysm TODO.
51  */
52 static void real_mode_switch_call_vsm(unsigned long smm, unsigned long sysm)
53 {
54         u16 entryHi = (VSA2_ENTRY_POINT & 0xffff0000) >> 4;
55         u16 entryLo = (VSA2_ENTRY_POINT & 0xffff);
56
57         __asm__ __volatile__(
58                 /* Paranoia -- does ecx get saved? not sure. This is
59                  * the easiest safe thing to do.
60                  */
61                 "       pushal                  \n"
62                 /* Save the stack. */
63                 "       mov     %%esp, __stack  \n"
64                 "       jmp     1f              \n"
65                 "__stack: .long 0               \n" 
66                 "1:\n"
67                 /* Get devfn into %%ecx. */
68                 "       movl    %%esp, %%ebp    \n"
69                 /* Get the smm and sysm args into ecx and edx. */
70                 "       movl    %0, %%ecx       \n"
71                 "       movl    %1, %%edx       \n"
72                 /* Load 'our' gdt. */
73                 "       lgdt    %%cs:__mygdtaddr        \n"
74                 /* This configures CS properly for real mode. */
75                 "       ljmp    $0x28, $__rms_16bit\n"
76                 "__rms_16bit:                   \n"
77                 "       .code16                 \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.
82                  */
83                 "       mov     $0x30, %%ax     \n"
84                 "       mov     %%ax, %%ds              \n"
85                 "       mov     %%ax, %%es              \n"
86                 "       mov     %%ax, %%fs              \n"
87                 "       mov     %%ax, %%gs              \n"
88                 "       mov     %%ax, %%ss              \n"
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"
95                 "__rms_real:                    \n"
96
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.
100                  */
101
102                 /* Setup a stack. */
103                 "       mov     $0x0, %%ax      \n"
104                 "       mov     %%ax, %%ss      \n"
105                 "       movl    $0x1000, %%eax  \n"
106                 "       movl    %%eax, %%esp    \n"
107                 /* Dump zeros in the other segregs. */
108                 "       mov     %%ax, %%es      \n"
109                 /* FIXME: Big real mode for gs, fs? */
110                 "       mov     %%ax, %%fs      \n"
111                 "       mov     %%ax, %%gs      \n"
112                 "       mov     $0x40, %%ax     \n"
113                 "       mov     %%ax, %%ds      \n"
114                 /* "     mov     %%cx, %%ax      \n" */
115                 "       movl    %0, %%ecx       \n"
116                 "       movl    %1, %%edx       \n"
117                 /* Call the VSA2 entry point address. */
118                 "       lcall   %2, %3\n"
119                 /* If we got here, just about done.
120                  * Need to get back to protected mode.
121                  */
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.
127                  */
128                 "       data32  ljmp    $0x10, $vsmrestart\n"
129                 "vsmrestart:\n"
130                 "       .code32\n"
131                 "       movw    $0x18, %%ax     \n"
132                 "       mov     %%ax, %%ds      \n"
133                 "       mov     %%ax, %%es      \n"
134                 "       mov     %%ax, %%fs      \n"
135                 "       mov     %%ax, %%gs      \n"
136                 "       mov     %%ax, %%ss      \n"
137                 /* Restore proper gdt. */
138                 "       lgdt    %%cs:gdtarg     \n"
139                 ".globl vsm_exit                \n"
140                 "vsm_exit:                      \n"
141                 "       mov     __stack, %%esp  \n"
142                 "       popal                   \n"::
143                 "g" (smm), "g"(sysm), "g"(entryHi), "g"(entryLo)
144         );
145 }
146
147 __asm__(".text\n" "real_mode_switch_end:\n");
148 extern char real_mode_switch_end[];
149
150 /* andrei: Some VSA virtual register helpers: raw read and MSR read. */
151
152 u32 VSA_vrRead(u16 classIndex)
153 {
154         unsigned eax, ebx, ecx, edx;
155         asm volatile (
156                 "movw   $0x0AC1C, %%dx          \n"
157                 "orl    $0x0FC530000, %%eax     \n"
158                 "outl   %%eax, %%dx             \n"
159                 "addb   $2, %%dl                \n"
160                 "inw    %%dx, %%ax              \n"
161                 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx) 
162                 : "a"(classIndex)
163         );
164
165         return eax;
166 }
167
168 u32 VSA_msrRead(u32 msrAddr)
169 {
170         unsigned eax, ebx, ecx, edx;
171         asm volatile (
172                 "movw   $0x0AC1C, %%dx                  \n"
173                 "movl   $0x0FC530007, %%eax             \n"
174                 "outl   %%eax, %%dx                             \n"
175                 "addb   $2, %%dl                                \n"
176                 "inw    %%dx, %%ax                              \n"
177                 : "=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
178                 : "c"(msrAddr)
179         );
180
181         return eax;
182 }
183
184 void do_vsmbios(void)
185 {
186         unsigned char *buf;
187         int i;
188
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 */
194 /*
195         init_archive(&archive);
196
197         if (find_file(&archive, "blob/vsa", &file))
198                 die("FATAL: NO VSA found!\n");
199
200         if (process_file(&file, (void *)VSA2_BUFFER))
201                 die("FATAL: Processing /blob/vsa failed\n");
202  */
203
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,
208          * don't bother.
209          */
210         if ((buf[0x20] != 0xb0) || (buf[0x21] != 0x10) ||
211             (buf[0x22] != 0xe6) || (buf[0x23] != 0x80)) {
212                 die("FATAL: no vsainit.bin signature, skipping!\n");
213         }
214
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);
218
219         /* Restart Timer 1. */
220         outb(0x56, 0x43);
221         outb(0x12, 0x41);
222
223         /* Check that VSA is running OK. */
224         if (VSA_vrRead(SIGNATURE) == VSA2_SIGNATURE)
225                 printk_debug("do_vsmbios: VSA2 VR signature verified\n");
226         else
227                 die("FATAL: VSA2 VR signature not valid, install failed!\n");
228 }
229