blob: f1a96ac1c4ad828c2dfd99b13ddb71bfa32268ba [file] [log] [blame]
Kevin O'Connor18e38b22008-12-10 20:40:13 -05001// Code for handling calls to "post" that are resume related.
2//
Kevin O'Connor14458432009-05-23 18:21:18 -04003// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connor18e38b22008-12-10 20:40:13 -05004//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05005// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor18e38b22008-12-10 20:40:13 -05006
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
Kevin O'Connor9967ab72008-12-18 21:57:33 -050011#include "bregs.h" // struct bregs
12#include "acpi.h" // find_resume_vector
Kevin O'Connor87b533b2011-07-10 22:35:07 -040013#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.
18int HaveRunPost VAR16VISIBLE;
Kevin O'Connor18e38b22008-12-10 20:40:13 -050019
20// Reset DMA controller
21void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050022init_dma(void)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050023{
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.
34void VISIBLE16
Kevin O'Connor87b533b2011-07-10 22:35:07 -040035handle_resume(void)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050036{
Kevin O'Connora0263082012-04-14 20:22:18 -040037 ASSERT16();
Kevin O'Connor18e38b22008-12-10 20:40:13 -050038 debug_serial_setup();
Kevin O'Connor87b533b2011-07-10 22:35:07 -040039 int status = inb_cmos(CMOS_RESET_CODE);
40 outb_cmos(0, CMOS_RESET_CODE);
Kevin O'Connor18e38b22008-12-10 20:40:13 -050041 dprintf(1, "In resume (status=%d)\n", status);
42
Kevin O'Connor87b533b2011-07-10 22:35:07 -040043 init_dma();
44
Kevin O'Connor18e38b22008-12-10 20:40:13 -050045 switch (status) {
Kevin O'Connor87b533b2011-07-10 22:35:07 -040046 case 0x01 ... 0x04:
47 case 0x06 ... 0x09:
48 panic("Unimplemented shutdown status: %02x\n", status);
Kevin O'Connor18e38b22008-12-10 20:40:13 -050049
50 case 0x05:
51 // flush keyboard (issue EOI) and jump via 40h:0067h
52 eoi_pic2();
53 // NO BREAK
54 case 0x0a:
Kevin O'Connor9f985422009-09-09 11:34:39 -040055#define BDA_JUMP (((struct bios_data_area_s *)0)->jump)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050056 // resume execution by jump via 40h:0067h
Kevin O'Connor18e38b22008-12-10 20:40:13 -050057 asm volatile(
Kevin O'Connor590e7152009-01-19 12:53:54 -050058 "movw %w1, %%ds\n"
Kevin O'Connor18e38b22008-12-10 20:40:13 -050059 "ljmpw *%0\n"
Kevin O'Connor9f985422009-09-09 11:34:39 -040060 : : "m"(BDA_JUMP), "r"(SEG_BDA)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050061 );
62 break;
63
64 case 0x0b:
65 // resume execution via IRET via 40h:0067h
66 asm volatile(
Kevin O'Connor590e7152009-01-19 12:53:54 -050067 "movw %w1, %%ds\n"
68 "lssw %0, %%sp\n"
Kevin O'Connor18e38b22008-12-10 20:40:13 -050069 "iretw\n"
Kevin O'Connor9f985422009-09-09 11:34:39 -040070 : : "m"(BDA_JUMP), "r"(SEG_BDA)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050071 );
72 break;
73
74 case 0x0c:
75 // resume execution via RETF via 40h:0067h
76 asm volatile(
Kevin O'Connor590e7152009-01-19 12:53:54 -050077 "movw %w1, %%ds\n"
78 "lssw %0, %%sp\n"
Kevin O'Connor18e38b22008-12-10 20:40:13 -050079 "lretw\n"
Kevin O'Connor9f985422009-09-09 11:34:39 -040080 : : "m"(BDA_JUMP), "r"(SEG_BDA)
Kevin O'Connor18e38b22008-12-10 20:40:13 -050081 );
82 break;
Kevin O'Connor87b533b2011-07-10 22:35:07 -040083
84 default:
85 break;
Kevin O'Connor18e38b22008-12-10 20:40:13 -050086 }
87
Kevin O'Connor87b533b2011-07-10 22:35:07 -040088 // Not a 16bit resume - do remaining checks in 32bit mode
89 asm volatile(
90 "movw %w1, %%ss\n"
91 "movl %0, %%esp\n"
92 "movl $_cfunc32flat_handle_resume32, %%edx\n"
93 "jmp transition32\n"
94 : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0), "a"(status)
95 );
Kevin O'Connor18e38b22008-12-10 20:40:13 -050096}
Kevin O'Connor9967ab72008-12-18 21:57:33 -050097
Kevin O'Connor87b533b2011-07-10 22:35:07 -040098// Handle an S3 resume event
99static void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500100s3_resume(void)
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500101{
Kevin O'Connorb24c5742009-01-17 21:52:52 -0500102 if (!CONFIG_S3_RESUME)
Kevin O'Connor87b533b2011-07-10 22:35:07 -0400103 return;
Kevin O'Connorb24c5742009-01-17 21:52:52 -0500104
Kevin O'Connor87b533b2011-07-10 22:35:07 -0400105 u32 s3_resume_vector = find_resume_vector();
106 if (!s3_resume_vector) {
107 dprintf(1, "No resume vector set!\n");
108 return;
109 }
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500110
Gleb Natapovecae9bf2012-01-24 14:33:42 +0200111 pic_setup();
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500112 smm_init();
113
Kevin O'Connord282af72009-07-04 04:10:32 -0400114 s3_resume_vga_init();
115
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500116 make_bios_readonly();
117
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500118 // Invoke the resume vector.
119 struct bregs br;
120 memset(&br, 0, sizeof(br));
Kevin O'Connor87b533b2011-07-10 22:35:07 -0400121 dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector);
122 br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector);
Kevin O'Connorc7ffbac2012-03-25 11:04:10 -0400123 farcall16big(&br);
Kevin O'Connor9967ab72008-12-18 21:57:33 -0500124}
Kevin O'Connor87b533b2011-07-10 22:35:07 -0400125
126// Attempt to invoke a hard-reboot.
127static void
128tryReboot(void)
129{
130 dprintf(1, "Attempting a hard reboot\n");
131
132 // Setup for reset on qemu.
133 if (! CONFIG_COREBOOT) {
134 qemu_prep_reset();
135 if (HaveRunPost)
136 apm_shutdown();
137 }
138
139 // Try keyboard controller reboot.
140 i8042_reboot();
141
142 // Try PCI 0xcf9 reboot
143 pci_reboot();
144
145 // Try triple fault
146 asm volatile("int3");
147
148 panic("Could not reboot");
149}
150
151void VISIBLE32FLAT
152handle_resume32(int status)
153{
154 ASSERT32FLAT();
155 dprintf(1, "In 32bit resume\n");
156
157 if (status == 0xfe)
158 s3_resume();
159
160 // Must be a soft reboot - invoke a hard reboot.
161 tryReboot();
162}