1
0

s3.c 2.1 KB

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