diff --git a/ChangeLog b/ChangeLog index 273cdbacf..e50bef916 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2012-02-26 Vladimir Serbinenko + + Fix interrupt mixup from previous commit. + + * include/grub/i386/pc/int.h (grub_i386_idt): New struct. + (grub_realidt): New var. + * grub-core/lib/i386/relocator16.S (grub_relocator16_idt): New variable + Load idt. + * grub-core/lib/i386/relocator.c (grub_relocator16_idt): + New declaration. + (grub_relocator16_boot): Set grub_relocator16_idt. + * grub-core/kern/i386/realmode.S (realidt): Renamed to ... + (LOCAL(realidt)): ... this. + * grub-core/boot/i386/pc/startup_raw.S: Pass pointer to realidt in eax. + * grub-core/kern/i386/pc/startup.S: Save pointer to realidt. + (grub_realidt): New variable. + 2012-02-26 Vladimir Serbinenko * grub-core/lib/i386/backtrace.c (grub_cmd_backtrace): Move from ... diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index fdd408702..413c0e944 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -343,6 +343,7 @@ post_reed_solomon: movl LOCAL(boot_dev), %edx movl $prot_to_real, %edi movl $real_to_prot, %ecx + movl $LOCAL(realidt), %eax jmp *%esi #ifdef ENABLE_LZMA diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 51e19b7f0..5b7ea9ae3 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -56,6 +56,7 @@ _start: movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi) movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi) + movl %eax, (EXT_C(grub_realidt) - _start) (%esi) /* copy back the decompressed part (except the modules) */ movl $(_edata - _start), %ecx @@ -177,6 +178,9 @@ FUNCTION(grub_pxe_call) #include "../int.S" +VARIABLE(grub_realidt) + .long 0 + .bss VARIABLE(grub_boot_device) .long 0 diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index a91adc3cd..b4e2f65c1 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -118,7 +118,7 @@ gdt: gdtdesc: .word 0x27 /* limit */ .long gdt /* addr */ -realidt: +LOCAL(realidt): .word 0 .long 0 protidt: @@ -175,7 +175,7 @@ protcseg: /* zero %eax */ xorl %eax, %eax - sidt realidt + sidt LOCAL(realidt) lidt protidt /* return on the old (or initialized) stack! */ @@ -205,7 +205,7 @@ prot_to_real: lgdt gdtdesc sidt protidt - lidt realidt + lidt LOCAL(realidt) /* save the protected mode stack */ movl %esp, %eax diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 74379f6f0..90af4035a 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -26,6 +26,7 @@ #include #include #include +#include extern grub_uint8_t grub_relocator_forward_start; extern grub_uint8_t grub_relocator_forward_end; @@ -79,6 +80,7 @@ extern grub_uint64_t grub_relocator64_rip_addr; extern grub_uint64_t grub_relocator64_rsp; extern grub_uint64_t grub_relocator64_rsi; extern grub_addr_t grub_relocator64_cr3; +extern struct grub_i386_idt grub_relocator16_idt; #define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) @@ -223,6 +225,12 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_ebx = state.ebx; grub_relocator16_edx = state.edx; grub_relocator16_esi = state.esi; +#ifdef GRUB_MACHINE_PCBIOS + grub_relocator16_idt = *grub_realidt; +#else + grub_relocator16_idt.base = 0; + grub_relocator16_idt.limit = 0; +#endif grub_relocator16_keep_a20_enabled = state.a20; diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index 30629dbe1..d5f5f3f03 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -76,6 +76,8 @@ VARIABLE(grub_relocator16_start) movl %esi, %eax shrl $4, %eax movw %ax, (LOCAL (segment) - LOCAL (base)) (%esi, 1) + + lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) (%esi, 1) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) @@ -278,4 +280,7 @@ LOCAL(cs_base_byte3): .byte 0, 0x92, 0, 0 LOCAL(gdt_end): +VARIABLE(grub_relocator16_idt) + .word 0 + .long 0 VARIABLE(grub_relocator16_end) diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h index 337752587..44e7f52bb 100644 --- a/include/grub/i386/pc/int.h +++ b/include/grub/i386/pc/int.h @@ -51,8 +51,16 @@ struct grub_bios_int_registers #define GRUB_CPU_INT_FLAGS_DEFAULT 0 #endif - void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno, struct grub_bios_int_registers *regs); +struct grub_i386_idt +{ + grub_uint16_t limit; + grub_uint32_t base; +} __attribute__ ((packed)); + +#ifdef GRUB_MACHINE_PCBIOS +extern struct grub_i386_idt *EXPORT_VAR(grub_realidt); +#endif #endif