1 #include "libcflat.h"
2 #include "acpi.h"
3 #include "asm/io.h"
4
5 #define RTC_SECONDS_ALARM 1
6 #define RTC_MINUTES_ALARM 3
7 #define RTC_HOURS_ALARM 5
8 #define RTC_ALARM_DONT_CARE 0xC0
9
10 #define RTC_REG_A 10
11 #define RTC_REG_B 11
12 #define RTC_REG_C 12
13
14 #define REG_A_UIP 0x80
15 #define REG_B_AIE 0x20
16
rtc_in(u8 reg)17 static inline int rtc_in(u8 reg)
18 {
19 outb(reg, 0x70);
20 return inb(0x71);
21 }
22
rtc_out(u8 reg,u8 val)23 static inline void rtc_out(u8 reg, u8 val)
24 {
25 outb(reg, 0x70);
26 outb(val, 0x71);
27 }
28
29 extern char resume_start, resume_end;
30
main(int argc,char ** argv)31 int main(int argc, char **argv)
32 {
33 struct acpi_table_facs_rev1 *facs = find_acpi_table_addr(FACS_SIGNATURE);
34 struct acpi_table_fadt *fadt = find_acpi_table_addr(FACP_SIGNATURE);
35 char *addr, *resume_vec = (void*)0x1000;
36
37 assert(facs);
38 facs->firmware_waking_vector = (u32)(ulong)resume_vec;
39
40 printf("FACS is at %p\n", facs);
41 printf("resume vector addr is %p\n", &facs->firmware_waking_vector);
42 for (addr = &resume_start; addr < &resume_end; addr++)
43 *resume_vec++ = *addr;
44 printf("copy resume code from %p\n", &resume_start);
45
46 printf("PM1a event registers at %" PRIx32 "\n", fadt->pm1a_evt_blk);
47 outw(0x400, fadt->pm1a_evt_blk + 2);
48
49 /* Setup RTC alarm to wake up on the next second. */
50 while ((rtc_in(RTC_REG_A) & REG_A_UIP) == 0);
51 while ((rtc_in(RTC_REG_A) & REG_A_UIP) != 0);
52 rtc_in(RTC_REG_C);
53 rtc_out(RTC_SECONDS_ALARM, RTC_ALARM_DONT_CARE);
54 rtc_out(RTC_MINUTES_ALARM, RTC_ALARM_DONT_CARE);
55 rtc_out(RTC_HOURS_ALARM, RTC_ALARM_DONT_CARE);
56 rtc_out(RTC_REG_B, rtc_in(RTC_REG_B) | REG_B_AIE);
57
58 *(volatile int*)0 = 0;
59 asm volatile("outw %0, %1" :: "a"((short)0x2400), "d"((short)fadt->pm1a_cnt_blk):"memory");
60 while(1)
61 *(volatile int*)0 = 1;
62
63 return 0;
64 }
65
66 asm (
67 ".global resume_start\n"
68 ".global resume_end\n"
69 ".code16\n"
70 "resume_start:\n"
71 "mov 0x0, %eax\n"
72 "mov $0xf4, %dx\n"
73 "out %eax, %dx\n"
74 "1: hlt\n"
75 "jmp 1b\n"
76 "resume_end:\n"
77 #ifdef __i386__
78 ".code32\n"
79 #else
80 ".code64\n"
81 #endif
82 );
83