/* drivemap_int13h.S - interrupt handler for the BIOS drive remapper */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008, 2009 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #include #define INT13H_OFFSET(x) ((x) - EXT_C(grub_drivemap_handler)) .code16 /* Copy starts here. When deployed, this code must be segment-aligned. */ /* The replacement int13 handler. Preserve all registers. */ FUNCTION(grub_drivemap_handler) /* Save %dx for future restore. */ push %dx /* Push flags. Used to simulate interrupt with original flags. */ pushf /* Map the drive number (always in DL). */ push %ax push %bx #ifdef APPLE_CC grub_drivemap_mapstart_ofs = INT13H_OFFSET(EXT_C(grub_drivemap_mapstart)) movw $grub_drivemap_mapstart_ofs, %bx #else movw $INT13H_OFFSET(EXT_C(grub_drivemap_mapstart)), %bx #endif more_remaining: movw %cs:(%bx), %ax cmpb %ah, %al jz not_found /* DRV=DST => map end - drive not remapped, keep DL. */ inc %bx inc %bx cmpb %dl, %al jnz more_remaining /* Not found, but more remaining, loop. */ movb %ah, %dl /* Found - drive remapped, modify DL. */ not_found: pop %bx pop %ax /* If the call isn't ah=0x8 or ah=0x15 we must restore %dx. */ cmpb $0x8, %ah jz norestore cmpb $0x15, %ah jz norestore /* Restore flags. */ popf pushf #ifdef APPLE_CC grub_drivemap_oldhandler_ofs = INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler)) lcall *%cs:grub_drivemap_oldhandler_ofs #else lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler)) #endif push %bp mov %sp, %bp tail: /* Save new flags below %esp so the caller will recieve new flags. */ pushf pop %dx mov %dx, 8(%bp) pop %bp /* Restore %dx. */ pop %dx iret norestore: /* Restore flags. */ popf pushf #ifdef APPLE_CC lcall *%cs:grub_drivemap_oldhandler_ofs #else lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler)) #endif push %bp mov %sp, %bp /* Save %dx. So it won't be restored to original value. */ mov %dx, 2(%bp) jmp tail /* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode IVT entries (thus PI:SC in mem). */ VARIABLE(grub_drivemap_oldhandler) .word 0x0, 0x0 /* This label MUST be at the end of the copied block, since the installer code reserves additional space for mappings at runtime and copies them over it. */ .align 2 VARIABLE(grub_drivemap_mapstart)