123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include <grub/dl.h>
- #include <grub/misc.h>
- #include <grub/extcmd.h>
- #include <grub/i18n.h>
- #include <grub/machine/int.h>
- #include <grub/acpi.h>
- GRUB_MOD_LICENSE ("GPLv3+");
- static const struct grub_arg_option options[] =
- {
- {"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0},
- {0, 0, 0, 0, 0, 0}
- };
- static inline void __attribute__ ((noreturn))
- stop (void)
- {
- while (1)
- {
- asm volatile ("hlt");
- }
- }
- void __attribute__ ((noreturn))
- grub_halt (int no_apm)
- {
- struct grub_bios_int_registers regs;
- grub_acpi_halt ();
- if (no_apm)
- stop ();
-
- regs.eax = 0x5300;
- regs.ebx = 0;
- regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
- grub_bios_interrupt (0x15, ®s);
- if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
- stop ();
-
- regs.eax = 0x5304;
- regs.ebx = 0;
- regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
- grub_bios_interrupt (0x15, ®s);
-
- regs.eax = 0x5301;
- regs.ebx = 0;
- regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
- grub_bios_interrupt (0x15, ®s);
- if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
- stop ();
-
- regs.eax = 0x530E;
- regs.ebx = 0;
- regs.ecx = 0x0101;
- regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
- grub_bios_interrupt (0x15, ®s);
- if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
- stop ();
-
- regs.eax = 0x5307;
- regs.ebx = 1;
- regs.ecx = 3;
- regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
- grub_bios_interrupt (0x15, ®s);
-
- stop ();
- }
- static grub_err_t __attribute__ ((noreturn))
- grub_cmd_halt (grub_extcmd_context_t ctxt,
- int argc __attribute__ ((unused)),
- char **args __attribute__ ((unused)))
- {
- struct grub_arg_list *state = ctxt->state;
- int no_apm = 0;
- if (state[0].set)
- no_apm = 1;
- grub_halt (no_apm);
- }
- static grub_extcmd_t cmd;
- GRUB_MOD_INIT(halt)
- {
- cmd = grub_register_extcmd ("halt", grub_cmd_halt, 0, "[-n]",
- N_("Halt the system, if possible using APM."),
- options);
- }
- GRUB_MOD_FINI(halt)
- {
- grub_unregister_extcmd (cmd);
- }
|