/* -*-Asm-*- */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,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 . */ #include #include #include .file "lnxboot.S" #define CODE_ADDR 0x6000 #define CODE_LENG (code_end - start) #define DATA_ADDR ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200) #define BLCK_LENG 0x4000 .text .code16 .globl start, _start data_start: pushw %cs popw %ds xorl %eax, %eax xorl %ebx, %ebx call data_next data_next: popw %bx movw %cs, %ax shll $4, %eax leal 0x200 + data_start - data_next(%ebx,%eax), %eax movzbl setup_sects - data_next(%bx), %ecx shll $9, %ecx addl %ecx, %eax movl %eax, code32_start - data_next(%bx) jmp linux_next . = data_start + 0x1F1 setup_sects: .byte (CODE_LENG >> 9) root_flags: .word 0 syssize: .word 0 swap_dev: .word 0 ram_size: .word 0 vid_mode: .word 0 root_dev: .word 0 boot_flag: .word 0xAA55 start: _start: jmp linux_code .ascii "HdrS" // Header signature .word 0x0203 // Header version number realmode_swtch: .word 0, 0 // default_switch, SETUPSEG start_sys_seg: .word 0x1000 // obsolete version_ptr: .word 0 // version string ptr type_of_loader: .byte 0 // Filled in by boot loader loadflags: .byte 1 // Please load high setup_move_size: .word 0 // Unused code32_start: .long 0x100000 // 32-bit start address ramdisk_image: .long 0 // Loaded ramdisk image address ramdisk_size: .long 0 // Size of loaded ramdisk bootsect_kludge: .word 0, 0 heap_end_ptr: .word 0 pad1: .word 0 cmd_line_ptr: .long 0 // Command line ramdisk_max: .long 0xffffffff // Highest allowed ramdisk address gdt: .long 0, 0, 0, 0 // Must be zero .word 0xffff // 64 K segment size gdt_src1: .byte 0, 0 ,0 // Low 24 bits of source addy .byte 0x93 // Access rights .byte 0 // Extended access rights gdt_src2: .byte 0 // High 8 bits of source addy .word 0xffff // 64 K segment size gdt_dst1: .byte 0, 0, 0 // Low 24 bits of target addy .byte 0x93 // Access rights .byte 0 // Extended access rights gdt_dst2: .byte 0 // High 8 bits of source addy .long 0, 0, 0, 0 // More space for the BIOS reg_edx: .byte 0x80,0,0xFF,0xFF data_leng: .long 0 linux_code: movw %cs:(reg_edx - start), %dx linux_next: call normalize normalize: popw %bx subw $(normalize - start), %bx shrw $4, %bx movw %cs, %ax addw %bx, %ax pushw %ax pushw $(real_code - start) lret // jump to real_code real_code: subw $0x20, %ax movw %ax, %ds movw (setup_sects - data_start), %cx shlw $7, %cx // Setup stack xorw %si, %si movw %si, %ss movw $(CODE_ADDR), %sp pushl %esi pushl %edi // Move itself to 0:CODE_ADDR cld movw %cs, %ax movw %ax, %ds movw $(CODE_ADDR >> 4), %ax movw %ax, %es movw %si, %di rep movsl ljmp $(CODE_ADDR >> 4), $(real_code_2 - start) real_code_2: pushw %es popw %ds movl (ramdisk_image - start), %esi or %esi, %esi jnz 1f movl (code32_start - start), %esi 1: movl $0x200, %ecx addl %ecx, %esi movl $DATA_ADDR, %edi call move_memory movsbl %dh, %eax movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART) movsbl (reg_edx + 2 - start), %eax movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART) movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx call move_memory popl %edi popl %esi ljmp $(DATA_ADDR >> 4), $0 // Parameters: // esi: source address // edi: target address // ecx: number of bytes move_memory: incl %ecx andb $0xFE, %cl pushw %dx 1: pushl %esi pushl %edi pushl %ecx cmpl $BLCK_LENG, %ecx jbe 2f movl $BLCK_LENG, %ecx 2: pushl %ecx movl %esi, %eax movw %si, (gdt_src1 - start) shrl $16, %eax movb %al, (gdt_src1 + 2 - start) movb %ah, (gdt_src2 - start) movl %edi, %eax movw %di, (gdt_dst1 - start) shrl $16, %eax movb %al, (gdt_dst1 + 2 - start) movb %ah, (gdt_dst2 - start) movw $(gdt - start), %si movb $0x87, %ah shrw $1, %cx int $0x15 popl %eax popl %ecx popl %edi popl %esi jnc 2f movw $(err_int15_msg - start), %si jmp fail 2: leal (%esi, %eax), %esi leal (%edi, %eax), %edi subl %eax, %ecx jnz 1b popw %dx ret // Parameters: // si: message fail: movb $0x0e, %ah xorw %bx, %bx 1: lodsb (%si), %al int $0x10 cmpb $0, %al jne 1b 1: jmp 1b err_int15_msg: .ascii "move memory fails\0" . = (. & (~0x1FF)) + 0x1FF .byte 0 code_end: