Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


SEABIOS updates to support reset and to simplify
[palacios.git] / bios / seabios / src / resume.c
1 // Code for handling calls to "post" that are resume related.
2 //
3 // Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // dprintf
8 #include "ioport.h" // outb
9 #include "pic.h" // eoi_pic2
10 #include "biosvar.h" // struct bios_data_area_s
11 #include "bregs.h" // struct bregs
12 #include "acpi.h" // find_resume_vector
13 #include "ps2port.h" // i8042_reboot
14 #include "pci.h" // pci_reboot
15 #include "cmos.h" // inb_cmos
16
17 // Indicator if POST phase has been run.
18 int HaveRunPost VAR16VISIBLE;
19
20 // Reset DMA controller
21 void
22 init_dma(void)
23 {
24     // first reset the DMA controllers
25     outb(0, PORT_DMA1_MASTER_CLEAR);
26     outb(0, PORT_DMA2_MASTER_CLEAR);
27
28     // then initialize the DMA controllers
29     outb(0xc0, PORT_DMA2_MODE_REG);
30     outb(0x00, PORT_DMA2_MASK_REG);
31 }
32
33 // Handler for post calls that look like a resume.
34 void VISIBLE16
35 handle_resume(void)
36 {
37     debug_serial_setup();
38     int status = inb_cmos(CMOS_RESET_CODE);
39     outb_cmos(0, CMOS_RESET_CODE);
40     dprintf(1, "In resume (status=%d)\n", status);
41
42     init_dma();
43
44     switch (status) {
45     case 0x01 ... 0x04:
46     case 0x06 ... 0x09:
47         panic("Unimplemented shutdown status: %02x\n", status);
48
49     case 0x05:
50         // flush keyboard (issue EOI) and jump via 40h:0067h
51         eoi_pic2();
52         // NO BREAK
53     case 0x0a:
54 #define BDA_JUMP (((struct bios_data_area_s *)0)->jump)
55         // resume execution by jump via 40h:0067h
56         asm volatile(
57             "movw %w1, %%ds\n"
58             "ljmpw *%0\n"
59             : : "m"(BDA_JUMP), "r"(SEG_BDA)
60             );
61         break;
62
63     case 0x0b:
64         // resume execution via IRET via 40h:0067h
65         asm volatile(
66             "movw %w1, %%ds\n"
67             "lssw %0, %%sp\n"
68             "iretw\n"
69             : : "m"(BDA_JUMP), "r"(SEG_BDA)
70             );
71         break;
72
73     case 0x0c:
74         // resume execution via RETF via 40h:0067h
75         asm volatile(
76             "movw %w1, %%ds\n"
77             "lssw %0, %%sp\n"
78             "lretw\n"
79             : : "m"(BDA_JUMP), "r"(SEG_BDA)
80             );
81         break;
82
83     default:
84         break;
85     }
86
87     // Not a 16bit resume - do remaining checks in 32bit mode
88     asm volatile(
89         "movw %w1, %%ss\n"
90         "movl %0, %%esp\n"
91         "movl $_cfunc32flat_handle_resume32, %%edx\n"
92         "jmp transition32\n"
93         : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0), "a"(status)
94         );
95 }
96
97 // Handle an S3 resume event
98 static void
99 s3_resume(void)
100 {
101     if (!CONFIG_S3_RESUME)
102         return;
103
104     u32 s3_resume_vector = find_resume_vector();
105     if (!s3_resume_vector) {
106         dprintf(1, "No resume vector set!\n");
107         return;
108     }
109
110     smm_init();
111
112     s3_resume_vga_init();
113
114     make_bios_readonly();
115
116     // Invoke the resume vector.
117     struct bregs br;
118     memset(&br, 0, sizeof(br));
119     dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector);
120     br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector);
121     call16big(&br);
122 }
123
124 // Attempt to invoke a hard-reboot.
125 static void
126 tryReboot(void)
127 {
128     dprintf(1, "Attempting a hard reboot\n");
129
130     // Setup for reset on qemu.
131     if (! CONFIG_COREBOOT && !CONFIG_PALACIOS) {
132         qemu_prep_reset();
133         if (HaveRunPost)
134             apm_shutdown();
135     }
136
137     HaveRunPost=0;
138
139     dprintf(1,"Attempting i8042 reboot\n");
140
141     // Try keyboard controller reboot.
142     i8042_reboot();
143
144     dprintf(1,"Attempting PCI reboot\n");
145
146     // Try PCI 0xcf9 reboot
147     pci_reboot();
148
149     dprintf(1,"Attempting int3 reboot\n");
150
151     // Try triple fault
152     asm volatile("int3");
153
154     panic("Could not reboot");
155 }
156
157 void VISIBLE32FLAT
158 handle_resume32(int status)
159 {
160     ASSERT32FLAT();
161     dprintf(1, "In 32bit resume\n");
162
163     if (status == 0xfe)
164         s3_resume();
165
166     // Must be a soft reboot - invoke a hard reboot.
167     tryReboot();
168 }