blob: 2dda0e06b4391f5f35d293683f047cfdc6c59665 [file] [log] [blame] [edit]
/* -*-Asm-*- */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <multiboot.h>
.file "lnxboot.S"
#define CODE_ADDR 0x6000
#define CODE_SECTORS 1
#define DATA_ADDR ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define BLCK_LENG 0x4000
.text
.code16
.globl start, _start
data_start:
xorl %ebp, %ebp
jmp LOCAL(linux_next)
.org 0x1F1
setup_sects:
.byte CODE_SECTORS
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 LOCAL(linux_init)
.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 address. */
.byte 0x93 /* Access rights. */
.byte 0 /* Extended access rights. */
gdt_src2:
.byte 0 /* High 8 bits of source address. */
.word 0xffff /* 64 K segment size. */
gdt_dst1:
.byte 0, 0, 0 /* Low 24 bits of target address. */
.byte 0x93 /* Access rights. */
.byte 0 /* Extended access rights. */
gdt_dst2:
.byte 0 /* High 8 bits of source address. */
.long 0, 0, 0, 0 /* More space for the BIOS. */
reg_edx:
.byte 0x80, 0, 0xFF, 0xFF
data_leng:
.long 0
LOCAL(linux_init):
movw %cs:(reg_edx - start), %dx
movl %cs:(code32_start - start), %ebp
LOCAL(linux_next):
call LOCAL(normalize)
LOCAL(normalize):
popw %bx
subw $(LOCAL(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
/* 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:
xchgl %ebp, %esi
orl %esi, %esi
jnz 1f
movw %ds, %si
shll $4, %esi
addl %ebp, %esi
1:
pushw %es
popw %ds
movl $0x1000, %ecx
addl $0x200, %esi
movl $DATA_ADDR, %edi
call LOCAL(move_memory)
/* Check for multiboot signature. */
movl $DATA_ADDR, %edi
3:
movl %ss:(%edi), %eax
cmpl $MULTIBOOT_HEADER_MAGIC, %eax
jz 1f
addl $4, %edi
cmpl $(DATA_ADDR + 0x1000), %edi
jne 3b
movl (ramdisk_image - start), %esi
movl (ramdisk_size - start), %ecx
movl $(DATA_ADDR - 0x200), %edi
jmp 2f
1:
movl $(DATA_ADDR + 0x1000), %edi
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
2:
call LOCAL(move_memory)
movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
movb (reg_edx + 2 - start), %dh
movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1)
movb $0xFF, %dh
ljmp $(DATA_ADDR >> 4), $0
/*
* Parameters:
* esi: source address
* edi: target address
* ecx: number of bytes
*/
LOCAL(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 LOCAL(fail)
2:
addl %eax, %esi
addl %eax, %edi
subl %eax, %ecx
jnz 1b
popw %dx
ret
/*
* Parameters:
* si: message
*/
LOCAL(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"
.org (CODE_SECTORS * 512 + 512)