Commit missing files from last commit.
[seabios.git] / src / smm.c
1 /*
2  * smm.c
3  * SMM support for BIOS.
4  * 
5  * Copyright (C) 2002  MandrakeSoft S.A.
6  * Copyright (C) 2008  Nguyen Anh Quynh <aquynh@gmail.com>
7  * 
8  * This file may be distributed under the terms of the GNU GPLv3 license.
9  */
10
11 #include "types.h"
12 #include "pci.h"
13 #include "smm.h" // smm_init
14 #include "config.h" // CONFIG_*
15 #include "util.h" // memcpy
16
17 #ifdef CONFIG_SMM
18
19 asm (
20 "    .global smm_relocation_start                               \n"
21 "    .global smm_relocation_end                                 \n"
22 "    .global smm_code_start                                     \n"
23 "    .global smm_code_end                                       \n"
24 "                                                               \n"
25 "    .code16                                                    \n"
26 "    /* code to relocate SMBASE to 0xa0000 */                   \n"
27 "smm_relocation_start:                                          \n"
28 "    movl $0x38000 + 0x7efc, %ebx                               \n"
29 "    /* revision ID to see if x86_64 or x86 */                  \n"
30 "    mov (%ebx), %al                                            \n"
31 "    cmpb $0x64, %al                                            \n"
32 "    je 1f                                                      \n"
33 "    movl $0x38000 + 0x7ef8, %ebx                               \n"
34 "    jmp 2f                                                     \n"
35 "1:                                                             \n"
36 "    movl $0x38000 + 0x7f00, %ebx                               \n"
37 "2:                                                             \n"
38 "    movl $0xa0000, %eax                                        \n"
39 "    movl %eax, (%ebx)                                          \n"
40 "    /* indicate to the BIOS that the SMM code was executed */  \n"
41 "    mov $0x00, %al                                             \n"
42 "    movw $0xb3, %dx                                            \n"
43 "    outb %al, %dx                                              \n"
44 "    rsm                                                        \n"
45 "smm_relocation_end:                                            \n"
46 "                                                               \n"
47 "    /* minimal SMM code to enable or disable ACPI */           \n"
48 "smm_code_start:                                                \n"
49 "    movw $0xb2, %dx                                            \n"
50 "    inb %dx, %al                                               \n"
51 "    cmp $0xf0, %al                                             \n"
52 "    jne 1f                                                     \n"
53 "                                                               \n"
54 "    /* ACPI disable */                                         \n"
55 "    //mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */                \n"
56 "    mov $0xb000 + 0x04, %dx /* PMCNTRL */                      \n"
57 "    inw %dx, %ax                                               \n"
58 "    andw $~1, %ax                                              \n"
59 "    outw %ax, %dx                                              \n"
60 "                                                               \n"
61 "    jmp 2f                                                     \n"
62 "1:                                                             \n"
63 "    cmp $0xf1, %al                                             \n"
64 "    jne 2f                                                     \n"
65 "                                                               \n"
66 "    /* ACPI enable */                                          \n"
67 "    //mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */                \n"
68 "    mov $0xb000 + 0x04, %dx /* PMCNTRL */                      \n"
69 "    inw %dx, %ax                                               \n"
70 "    orw $1, %ax                                                \n"
71 "    outw %ax, %dx                                              \n"
72 "                                                               \n"
73 "2:                                                             \n"
74 "    rsm                                                        \n"
75 "smm_code_end:                                                  \n"
76 "    .code32                                                    \n"
77     );
78
79 extern u8 smm_relocation_start, smm_relocation_end;
80 extern u8 smm_code_start, smm_code_end;
81
82 void
83 smm_init(PCIDevice *d)
84 {
85     u32 value;
86
87     /* check if SMM init is already done */
88     value = pci_config_readl(d, 0x58);
89     if ((value & (1 << 25)) == 0) {
90         /* copy the SMM relocation code */
91         memcpy((void *)0x38000, &smm_relocation_start,
92                &smm_relocation_end - &smm_relocation_start);
93
94         /* enable SMI generation when writing to the APMC register */
95         pci_config_writel(d, 0x58, value | (1 << 25));
96
97         /* init APM status port */
98         outb(0x01, 0xb3);
99
100         /* raise an SMI interrupt */
101         outb(0x00, 0xb2);
102
103         /* wait until SMM code executed */
104         while (inb(0xb3) != 0x00);
105
106         /* enable the SMM memory window */
107         pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
108
109         /* copy the SMM code */
110         memcpy((void *)0xa8000, &smm_code_start,
111                &smm_code_end - &smm_code_start);
112         wbinvd();
113
114         /* close the SMM memory window and enable normal SMM */
115         pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
116     }
117 }
118 #endif