+ // Not a 16bit resume - do remaining checks in 32bit mode
+ asm volatile(
+ "movw %w1, %%ss\n"
+ "movl %0, %%esp\n"
+ "movl $_cfunc32flat_handle_resume32, %%edx\n"
+ "jmp transition32\n"
+ : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0), "a"(status)
+ );
+}
+
+// Handle an S3 resume event
+static void
+s3_resume(void)
+{
+ if (!CONFIG_S3_RESUME)
+ return;
+
+ u32 s3_resume_vector = find_resume_vector();
+ if (!s3_resume_vector) {
+ dprintf(1, "No resume vector set!\n");
+ return;
+ }
+
+ pic_setup();
+ smm_init();
+
+ s3_resume_vga_init();
+
+ make_bios_readonly();
+
+ // Invoke the resume vector.
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector);
+ br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector);
+ call16big(&br);
+}
+
+// Attempt to invoke a hard-reboot.
+static void
+tryReboot(void)
+{
+ dprintf(1, "Attempting a hard reboot\n");
+
+ // Setup for reset on qemu.
+ if (! CONFIG_COREBOOT) {
+ qemu_prep_reset();
+ if (HaveRunPost)
+ apm_shutdown();
+ }
+
+ // Try keyboard controller reboot.
+ i8042_reboot();
+
+ // Try PCI 0xcf9 reboot
+ pci_reboot();
+
+ // Try triple fault
+ asm volatile("int3");
+
+ panic("Could not reboot");
+}
+
+void VISIBLE32FLAT
+handle_resume32(int status)
+{
+ ASSERT32FLAT();
+ dprintf(1, "In 32bit resume\n");
+
+ if (status == 0xfe)
+ s3_resume();
+
+ // Must be a soft reboot - invoke a hard reboot.
+ tryReboot();