]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
intwrapped halt
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 4 Apr 2010 16:42:48 +0000 (18:42 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 4 Apr 2010 16:42:48 +0000 (18:42 +0200)
commands/i386/pc/halt.c
include/grub/misc.h
kern/i386/pc/startup.S

index 4c39612ae81f22db67a85904d7ed1d457f917486..c237fe361ed1a1382defd850b606215dbeefdffb 100644 (file)
@@ -21,6 +21,7 @@
 #include <grub/misc.h>
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
+#include <grub/machine/int.h>
 
 static const struct grub_arg_option options[] =
   {
@@ -28,6 +29,69 @@ static const struct grub_arg_option options[] =
     {0, 0, 0, 0, 0, 0}
   };
 
+static inline void __attribute__ ((noreturn))
+stop (void)
+{
+  while (1)
+    {
+      asm volatile ("hlt");
+    }
+}
+/*
+ * Halt the system, using APM if possible. If NO_APM is true, don't use
+ * APM even if it is available.
+ */
+void 
+grub_halt (int no_apm)
+{
+  struct grub_bios_int_registers regs;
+
+  if (no_apm)
+    stop ();
+
+  /* detect APM */
+  regs.eax = 0x5300;
+  regs.ebx = 0;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x15, &regs);
+  
+  if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+    stop ();
+
+  /* disconnect APM first */
+  regs.eax = 0x5304;
+  regs.ebx = 0;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x15, &regs);
+
+  /* connect APM */
+  regs.eax = 0x5301;
+  regs.ebx = 0;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x15, &regs);
+  if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+    stop ();
+
+  /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
+  regs.eax = 0x530E;
+  regs.ebx = 0;
+  regs.ecx = 0x0101;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x15, &regs);
+  if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+    stop ();
+
+  /* set the power state to off */
+  regs.eax = 0x5307;
+  regs.ebx = 1;
+  regs.ecx = 3;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x15, &regs);
+
+  /* shouldn't reach here */
+  stop ();
+}
+
 static grub_err_t
 grub_cmd_halt (grub_extcmd_t cmd,
               int argc __attribute__ ((unused)),
index 61174c38d355dd3ab06972dc8eb763eb40512b46..95c7664f152fbde522be15bf136caade7c11bf0e 100644 (file)
@@ -298,7 +298,7 @@ void EXPORT_FUNC (grub_reboot) (void);
 #ifdef GRUB_MACHINE_PCBIOS
 /* Halt the system, using APM if possible. If NO_APM is true, don't
  * use APM even if it is available.  */
-void EXPORT_FUNC (grub_halt) (int no_apm);
+void grub_halt (int no_apm);
 #else
 void EXPORT_FUNC (grub_halt) (void);
 #endif
index ef58c738c6868ff495be0d2d2ad1889235785acc..4c7c74ec777e98e808de4210bc3f7c9b5f1fb54e 100644 (file)
@@ -450,16 +450,6 @@ gate_a20_check_state:
  */
        . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
 
-       /*
-        * This next part is sort of evil.  It takes advantage of the
-        * byte ordering on the x86 to work in either 16-bit or 32-bit
-        * mode, so think about it before changing it.
-        */
-
-FUNCTION(grub_hard_stop)
-       hlt
-       jmp EXT_C(grub_hard_stop)
-
 
 /*
  * grub_stop_floppy()
@@ -486,56 +476,6 @@ FUNCTION(grub_exit)
        jmp     cold_reboot
        .code32
 
-/*
- * grub_halt(int no_apm)
- *
- * Halt the system, using APM if possible. If NO_APM is true, don't use
- * APM even if it is available.
- */
-FUNCTION(grub_halt)
-       /* see if zero */
-       testl   %eax, %eax
-       jnz     EXT_C(grub_stop)
-
-       call    prot_to_real
-       .code16
-
-       /* detect APM */
-       movw    $0x5300, %ax
-       xorw    %bx, %bx
-       int     $0x15
-       jc      EXT_C(grub_hard_stop)
-       /* don't check %bx for buggy BIOSes... */
-
-       /* disconnect APM first */
-       movw    $0x5304, %ax
-       xorw    %bx, %bx
-       int     $0x15
-
-       /* connect APM */
-       movw    $0x5301, %ax
-       xorw    %bx, %bx
-       int     $0x15
-       jc      EXT_C(grub_hard_stop)
-
-       /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
-       movw    $0x530E, %ax
-       xorw    %bx, %bx
-       movw    $0x0101, %cx
-       int     $0x15
-       jc      EXT_C(grub_hard_stop)
-
-       /* set the power state to off */
-       movw    $0x5307, %ax
-       movw    $1, %bx
-       movw    $3, %cx
-       int     $0x15
-
-       /* shouldn't reach here */
-       jmp     EXT_C(grub_hard_stop)
-       .code32
-
-
 /*
  *  void grub_chainloader_real_boot (int drive, void *part_addr)
  *