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