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 17 static inline int rtc_in(u8 reg) 18 { 19 outb(reg, 0x70); 20 return inb(0x71); 21 } 22 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 31 int main(int argc, char **argv) 32 { 33 struct acpi_table_fadt_rev1 *fadt = find_acpi_table_addr(FACP_SIGNATURE); 34 struct acpi_table_facs_rev1 *facs = find_acpi_table_addr(FACS_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