/* * 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; grub_acpi_halt (); if (no_apm) stop (); /* detect APM */ 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 (); /* disconnect APM first */ regs.eax = 0x5304; regs.ebx = 0; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x15, ®s); /* connect APM */ 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 (); /* 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, ®s); 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, ®s); /* shouldn't reach here */ stop (); }
/* Get a memory map entry. Return next continuation value. Zero means the end. */ static grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, grub_uint32_t cont) { struct grub_bios_int_registers regs; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; /* place address (+4) in ES:DI */ regs.es = ((grub_addr_t) &entry->addr) >> 4; regs.edi = ((grub_addr_t) &entry->addr) & 0xf; /* set continuation value */ regs.ebx = cont; /* set default maximum buffer size */ regs.ecx = sizeof (*entry) - sizeof (entry->size); /* set EDX to 'SMAP' */ regs.edx = 0x534d4150; regs.eax = 0xe820; grub_bios_interrupt (0x15, ®s); /* write length of buffer (zero if error) into ADDR */ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) || regs.eax != 0x534d4150 || regs.ecx < 0x14 || regs.ecx > 0x400) entry->size = 0; else entry->size = regs.ecx; /* return the continuation value */ return regs.ebx; }
/* * * grub_get_conv_memsize(i) : return the conventional memory size in KB. * BIOS call "INT 12H" to get conventional memory size * The return value in AX. */ static inline grub_uint16_t grub_get_conv_memsize (void) { struct grub_bios_int_registers regs; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x12, ®s); return regs.eax & 0xffff; }
static void int10_9 (grub_uint8_t ch, grub_uint16_t n) { struct grub_bios_int_registers regs; regs.eax = ch | 0x0900; regs.ebx = grub_console_cur_color & 0xff; regs.ecx = n; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x10, ®s); }
int grub_apm_get_info (struct grub_apm_info *info) { struct grub_bios_int_registers regs; /* detect APM */ 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) return 0; info->version = regs.eax & 0xffff; info->flags = regs.ecx & 0xffff; /* disconnect APM first */ regs.eax = 0x5304; regs.ebx = 0; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x15, ®s); /* connect APM */ regs.eax = 0x5303; regs.ebx = 0; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x15, ®s); if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) return 0; info->cseg = regs.eax & 0xffff; info->offset = regs.ebx; info->cseg_16 = regs.ecx & 0xffff; info->dseg = regs.edx & 0xffff; info->cseg_len = regs.esi >> 16; info->cseg_16_len = regs.esi & 0xffff; info->dseg_len = regs.edi; return 1; }
static inline grub_uint32_t grub_get_eisa_mmap (void) { struct grub_bios_int_registers regs; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; regs.eax = 0xe801; grub_bios_interrupt (0x15, ®s); if ((regs.eax & 0xff00) == 0x8600) return 0; return (regs.eax & 0xffff) | (regs.ebx << 16); }