split realmode and loader routines out of startup.S
PATCH 1/1 split realmode and loader routines out of startup.S
This patch splits realmode and loader routines out of startup.S. The idea is that the LinuxBIOS port can be adapted to share more code with the rest of GRUB instead of duplicating it.
This is quite critical stuff, so even if the change seems trivial I'd suggest being careful, since I don't trust myself too much. Of course, I've tested that it can still boot Linux and Multiboot (on qemu only). Perhaps testing on real hardware would be appropiate (but I don't have this handy atm).
Signature · 5 lines
Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.)
2007-10-16 Robert Millan <[email protected]>
* kern/i386/loader.S: New file.
* kern/i386/pc/startup.S (grub_linux_prot_size): Moved to ...
* kern/i386/loader.S (grub_linux_prot_size): ... here.
* kern/i386/pc/startup.S (grub_linux_tmp_addr): Moved to ...
* kern/i386/loader.S (grub_linux_tmp_addr): ... here.
* kern/i386/pc/startup.S (grub_linux_real_addr): Moved to ...
* kern/i386/loader.S (grub_linux_real_addr): ... here.
* kern/i386/pc/startup.S (grub_linux_boot_zimage): Moved to ...
* kern/i386/loader.S (grub_linux_boot_zimage): ... here.
* kern/i386/pc/startup.S (grub_linux_boot_bzimage): Moved to ...
* kern/i386/loader.S (grub_linux_boot_bzimage): ... here.
* kern/i386/pc/startup.S (grub_multiboot_real_boot): Moved to ...
* kern/i386/loader.S (grub_multiboot_real_boot): ... here.
* kern/i386/pc/startup.S (grub_multiboot2_real_boot): Moved to ...
* kern/i386/loader.S (grub_multiboot2_real_boot): ... here.
* kern/i386/realmode.S: New file.
* kern/i386/pc/startup.S (protstack): Moved to ...
* kern/i386/realmode.S (protstack): ... here.
* kern/i386/pc/startup.S (gdt): Moved to ...
* kern/i386/realmode.S (gdt): ... here.
* kern/i386/pc/startup.S (prot_to_real): Moved to ...
* kern/i386/realmode.S (prot_to_real): ... here.
* kern/i386/pc/startup.S: Include kern/i386/loader.S' and kern/i386/realmode.S'.
kern/i386/loader.S +157 -0
@@ -0,0 +1,157 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007 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 <http://www.gnu.org/licenses/>. + */ + + +/* + * Note: These functions defined in this file may be called from C. + * Be careful of that you must not modify some registers. Quote + * from gcc-2.95.2/gcc/config/i386/i386.h: + + 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. + + ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg +{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + */ + +/* + * Note: GRUB is compiled with the options -mrtd and -mregparm=3. + * So the first three arguments are passed in %eax, %edx, and %ecx, + * respectively, and if a function has a fixed number of arguments + * and the number if greater than three, the function must return + * with "ret $N" where N is ((the number of arguments) - 3) * 4. + */ + +/* + * This is the area for all of the special variables. + */ + + .p2align 2 /* force 4-byte alignment */ + +/* + * void grub_linux_boot_zimage (void) + */ +VARIABLE(grub_linux_prot_size) + .long 0 +VARIABLE(grub_linux_tmp_addr) + .long 0 +VARIABLE(grub_linux_real_addr) + .long 0 + +FUNCTION(grub_linux_boot_zimage) + /* copy the kernel */ + movl EXT_C(grub_linux_prot_size), %ecx + addl $3, %ecx + shrl $2, %ecx + movl $GRUB_LINUX_BZIMAGE_ADDR, %esi + movl $GRUB_LINUX_ZIMAGE_ADDR, %edi + cld + rep + movsl + +FUNCTION(grub_linux_boot_bzimage) + call EXT_C(grub_dl_unload_all) + + movl EXT_C(grub_linux_real_addr), %ebx + + /* copy the real mode code */ + movl EXT_C(grub_linux_tmp_addr), %esi + movl %ebx, %edi + movl $GRUB_LINUX_SETUP_MOVE_SIZE, %ecx + cld + rep + movsb + + /* change %ebx to the segment address */ + shrl $4, %ebx + movl %ebx, %eax + addl $0x20, %eax + movw %ax, linux_setup_seg + + /* XXX new stack pointer in safe area for calling functions */ + movl $0x4000, %esp + call EXT_C(grub_stop_floppy) + + /* final setup for linux boot */ + call prot_to_real + .code16 + + cli + movw %bx, %ss + movw $GRUB_LINUX_SETUP_STACK, %sp + + movw %bx, %ds + movw %bx, %es + movw %bx, %fs + movw %bx, %gs + + /* ljmp */ + .byte 0xea + .word 0 +linux_setup_seg: + .word 0 + .code32 + + +/* + * This starts the multiboot kernel. + */ + +FUNCTION(grub_multiboot_real_boot) + /* Push the entry address on the stack. */ + pushl %eax + /* Move the address of the multiboot information structure to ebx. */ + movl %edx,%ebx + + /* Unload all modules and stop the floppy driver. */ + call EXT_C(grub_dl_unload_all) + call EXT_C(grub_stop_floppy) + + /* Interrupts should be disabled. */ + cli + + /* Move the magic value into eax and jump to the kernel. */ + movl $MULTIBOOT_MAGIC2,%eax + popl %ecx + jmp *%ecx + +/* + * This starts the multiboot 2 kernel. + */ + +FUNCTION(grub_multiboot2_real_boot) + /* Push the entry address on the stack. */ + pushl %eax + /* Move the address of the multiboot information structure to ebx. */ + movl %edx,%ebx + + /* Unload all modules and stop the floppy driver. */ + call EXT_C(grub_dl_unload_all) + call EXT_C(grub_stop_floppy) + + /* Interrupts should be disabled. */ + cli + + /* Move the magic value into eax and jump to the kernel. */ + movl $MULTIBOOT2_BOOTLOADER_MAGIC,%eax + popl %ecx + jmp *%ecx
kern/i386/pc/startup.S +2 -233
266 lines not on this page · raw message
kern/i386/realmode.S +178 -0
178 lines not on this page · raw message
Quoted 8 lines · Robert Millan
This patch splits realmode and loader routines out of
startup.S. The idea is that the LinuxBIOS port can be adapted to share more code with the rest of GRUB instead of duplicating it.This is quite critical stuff, so even if the change seems trivial I'd suggest being careful, since I don't trust myself too much. Of course, I've tested that it can still boot Linux and Multiboot (on qemu only). Perhaps testing on real hardware would be appropiate (but I don't have this handy atm).
Neither have I. Hopefully someone else?
Quoted 6 lines
2007-10-16 Robert Millan <[email protected]>
*
kern/i386/loader.S: New file.*
kern/i386/pc/startup.S(grub_linux_prot_size): Moved to ...
*kern/i386/loader.S(grub_linux_prot_size): ... here.
I would say:
(...): Moved from here...
(...): ... to here.
Can you change that?
Quoted 22 lines
*
kern/i386/pc/startup.S(grub_linux_tmp_addr): Moved to ...
*kern/i386/loader.S(grub_linux_tmp_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_real_addr): Moved to ...
*kern/i386/loader.S(grub_linux_real_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_zimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_zimage): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_bzimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_bzimage): ... here.
*kern/i386/pc/startup.S(grub_multiboot_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot_real_boot): ... here.
*kern/i386/pc/startup.S(grub_multiboot2_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot2_real_boot): ... here.*
kern/i386/realmode.S: New file.*
kern/i386/pc/startup.S(protstack): Moved to ...
*kern/i386/realmode.S(protstack): ... here.
*kern/i386/pc/startup.S(gdt): Moved to ...
*kern/i386/realmode.S(gdt): ... here.
*kern/i386/pc/startup.S(prot_to_real): Moved to ...
*kern/i386/realmode.S(prot_to_real): ... here.
Quoted 2 lines
*
kern/i386/pc/startup.S: Includekern/i386/loader.S' andkern/i386/realmode.S'.
Why include? Can't it be linked? That's what a linker is for :-)
Please try to fix this.
--
Marco
Quoted 9 lines · Marco Gerards
Quoted 2 lines
*
kern/i386/pc/startup.S(grub_linux_prot_size): Moved to ...
*kern/i386/loader.S(grub_linux_prot_size): ... here.I would say:
(...): Moved from here...
(...): ... to here.Can you change that?
Ok (ACKed also for the next patch I already sent).
Quoted 22 lines
Quoted 22 lines
*
kern/i386/pc/startup.S(grub_linux_tmp_addr): Moved to ...
*kern/i386/loader.S(grub_linux_tmp_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_real_addr): Moved to ...
*kern/i386/loader.S(grub_linux_real_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_zimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_zimage): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_bzimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_bzimage): ... here.
*kern/i386/pc/startup.S(grub_multiboot_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot_real_boot): ... here.
*kern/i386/pc/startup.S(grub_multiboot2_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot2_real_boot): ... here.*
kern/i386/realmode.S: New file.*
kern/i386/pc/startup.S(protstack): Moved to ...
*kern/i386/realmode.S(protstack): ... here.
*kern/i386/pc/startup.S(gdt): Moved to ...
*kern/i386/realmode.S(gdt): ... here.
*kern/i386/pc/startup.S(prot_to_real): Moved to ...
*kern/i386/realmode.S(prot_to_real): ... here.
Quoted 4 lines
Quoted 2 lines
* kern/i386/pc/startup.S: Include `kern/i386/loader.S' and `kern/i386/realmode.S'.Why include? Can't it be linked? That's what a linker is for :-)
Linking required wrapping a lot of references with EXT_C() macro, so I opted for #include (note this is done for lzo1x.S already).
Also, #including stuff from the wrong [1] place caused cpu faults in my tests. With my current patch, code doesn't change much its location (real mode stuff at the beginning, loader stuff at the end).
[1] Sorry, I'm not sure what wrong means here. Maybe it has to do with GAS syntax magic affecting cross-include borders or with a weird hardcoded reference to a specific memory layout.
Signature · 5 lines
Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.)
Quoted 4 lines · Robert Millan
Quoted 3 lines · Marco Gerards
Quoted 2 lines
*
kern/i386/pc/startup.S(grub_linux_prot_size): Moved to ...
*kern/i386/loader.S(grub_linux_prot_size): ... here.
Quoted 8 lines
Quoted 6 lines
I would say:
(...): Moved from here...
(...): ... to here.Can you change that?
Ok (ACKed also for the next patch I already sent).
Great!
Quoted 22 lines
Quoted 22 lines
Quoted 22 lines
*
kern/i386/pc/startup.S(grub_linux_tmp_addr): Moved to ...
*kern/i386/loader.S(grub_linux_tmp_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_real_addr): Moved to ...
*kern/i386/loader.S(grub_linux_real_addr): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_zimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_zimage): ... here.
*kern/i386/pc/startup.S(grub_linux_boot_bzimage): Moved to ...
*kern/i386/loader.S(grub_linux_boot_bzimage): ... here.
*kern/i386/pc/startup.S(grub_multiboot_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot_real_boot): ... here.
*kern/i386/pc/startup.S(grub_multiboot2_real_boot): Moved to ...
*kern/i386/loader.S(grub_multiboot2_real_boot): ... here.*
kern/i386/realmode.S: New file.*
kern/i386/pc/startup.S(protstack): Moved to ...
*kern/i386/realmode.S(protstack): ... here.
*kern/i386/pc/startup.S(gdt): Moved to ...
*kern/i386/realmode.S(gdt): ... here.
*kern/i386/pc/startup.S(prot_to_real): Moved to ...
*kern/i386/realmode.S(prot_to_real): ... here.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
* kern/i386/pc/startup.S: Include `kern/i386/loader.S' and `kern/i386/realmode.S'.Why include? Can't it be linked? That's what a linker is for :-)
Linking required wrapping a lot of references with
EXT_C()macro, so I opted for #include (note this is done forlzo1x.Salready).
Is using EXT_C a problem? I don't know this code too well, unfortunately :(
Quoted 3 lines
Also, #including stuff from the wrong [1] place caused cpu faults in my tests. With my current patch, code doesn't change much its location (real mode stuff at the beginning, loader stuff at the end).
:-/
Quoted 3 lines
[1] Sorry, I'm not sure what wrong means here. Maybe it has to do with GAS syntax magic affecting cross-include borders or with a weird hardcoded reference to a specific memory layout.
I can't help you there.
--
Marco
Quoted 6 lines · Marco Gerards
Quoted 3 lines
Linking required wrapping a lot of references with
EXT_C()macro, so I opted for #include (note this is done forlzo1x.Salready).Is using
EXT_Ca problem? I don't know this code too well, unfortunately :(
No. Maybe linking bring in other problems, but EXT_C per se isn't a big deal. Though do we really want it? It doesn't seem to be a problem for lzo1x.S.
Signature · 5 lines
Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.)
Quoted 10 lines · Robert Millan
Quoted 6 lines · Marco Gerards
Quoted 3 lines
Linking required wrapping a lot of references with
EXT_C()macro, so I opted for #include (note this is done forlzo1x.Salready).Is using
EXT_Ca problem? I don't know this code too well, unfortunately :(No. Maybe linking bring in other problems, but
EXT_Cper se isn't a big deal. Though do we really want it? It doesn't seem to be a problem forlzo1x.S.
Including is not a big problem for me. It should just not become a common practise. It's easy to change so I am fine with it.
--
Marco
Committed.
Signature · 5 lines
Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.)
At Tue, 16 Oct 2007 23:09:07 +0200,
Quoted 8 lines · Robert Millan
This patch splits realmode and loader routines out of
startup.S. The idea is that the LinuxBIOS port can be adapted to share more code with the rest of GRUB instead of duplicating it.This is quite critical stuff, so even if the change seems trivial I'd suggest being careful, since I don't trust myself too much. Of course, I've tested that it can still boot Linux and Multiboot (on qemu only). Perhaps testing on real hardware would be appropiate (but I don't have this handy atm).
<SNIP>
Quoted 9 lines
*
kern/i386/pc/startup.S(protstack): Moved to ...
*kern/i386/realmode.S(protstack): ... here.
*kern/i386/pc/startup.S(gdt): Moved to ...
*kern/i386/realmode.S(gdt): ... here.
*kern/i386/pc/startup.S(prot_to_real): Moved to ...
*kern/i386/realmode.S(prot_to_real): ... here.*
kern/i386/pc/startup.S: Includekern/i386/loader.S' andkern/i386/realmode.S'.
Why did you move prot_to_real to realmode.S, but not real_to_prot? That seems a bit strange to me...
Jeroen Dekkers
Quoted 18 lines · Jeroen Dekkers
At Tue, 16 Oct 2007 23:09:07 +0200,
Quoted 8 lines · Robert Millan
This patch splits realmode and loader routines out of
startup.S. The idea is that the LinuxBIOS port can be adapted to share more code with the rest of GRUB instead of duplicating it.This is quite critical stuff, so even if the change seems trivial I'd suggest being careful, since I don't trust myself too much. Of course, I've tested that it can still boot Linux and Multiboot (on qemu only). Perhaps testing on real hardware would be appropiate (but I don't have this handy atm).
<SNIP>
Quoted 7 lines
*
kern/i386/pc/startup.S(protstack): Moved to ...
*kern/i386/realmode.S(protstack): ... here.
*kern/i386/pc/startup.S(gdt): Moved to ...
*kern/i386/realmode.S(gdt): ... here.
*kern/i386/pc/startup.S(prot_to_real): Moved to ...
*kern/i386/realmode.S(prot_to_real): ... here.
Quoted 5 lines
Quoted 2 lines
* kern/i386/pc/startup.S: Include `kern/i386/loader.S' and `kern/i386/realmode.S'.Why did you move
prot_to_realtorealmode.S, but notreal_to_prot? That seems a bit strange to me...
Because on i386-pc, GRUB wants to do both things, but on i386-linuxbios, you start in protected mode and only want to switch once to real mode when booting Linux. There's no way back AFAICT.
Signature · 5 lines
Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.)