/* -*-Asm-*- */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 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 . */ /* The signature for bootloader. */ #define GRUB_BOOT_MACHINE_SIGNATURE 0xaa55 /* The offset of a magic number used by Windows NT. */ #define GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC 0x1b8 /* The offset of the start of the partition table. */ #define GRUB_BOOT_MACHINE_PART_START 0x1be /* The offset of the end of the partition table. */ #define GRUB_BOOT_MACHINE_PART_END 0x1fe /* The stack segment. */ #define GRUB_BOOT_MACHINE_STACK_SEG 0x2000 /* The segment of disk buffer. The disk buffer MUST be 32K long and cannot straddle a 64K boundary. */ #define GRUB_BOOT_MACHINE_BUFFER_SEG 0x7000 /* The flag for BIOS drive number to designate a hard disk vs. a floppy. */ #define GRUB_BOOT_MACHINE_BIOS_HD_FLAG 0x80 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_MACHINE_KERNEL_SEG 0x800 /* The address where the kernel is loaded. */ #define GRUB_BOOT_MACHINE_KERNEL_ADDR (GRUB_BOOT_MACHINE_KERNEL_SEG << 4) /* The size of a block list used in the kernel startup code. */ #define GRUB_BOOT_MACHINE_LIST_SIZE 12 #define ABS(x) (x-_start+0x7c00) .code16 .globl _start; _start: jmp real_start stack: packet: .byte 0x10 .byte 0 .word 1 .word 0,GRUB_BOOT_MACHINE_KERNEL_SEG kernel_sector: .long 1, 0 h1: .long 0xefcdab89 h2: .long 0x98badcfe h3: .long 0x10325476 h4: .long 0xc3d2e1f0 h0: .long 0x67452301 real_start: cli xorw %ax, %ax movb $0x80, %dl movw %ax, %ds movw %ax, %es movw %ax, %ss mov $ABS(stack), %sp movw %sp, %si movb $0x42, %ah int $0x13 add $0x10,%sp mov ABS(byteshashed), %si block32: movw $GRUB_BOOT_MACHINE_KERNEL_SEG, %ax movw %ax, %ds incb %ah movw %ax, %es xor %ax,%ax mov %ax, %di mov $0x40, %cx push %cx cld rep movsb pop %cx movw $(GRUB_BOOT_MACHINE_KERNEL_SEG+0x100), %ax movw %ax, %ds expand: movl -12(%di), %eax xorl -32(%di), %eax xorl -56(%di), %eax xorl -64(%di), %eax shl $1, %eax adc $0, %al mov %eax, (%di) add $4, %di decw %cx test %cx, %cx jnz expand xor %ax, %ax mov %ax, %ds mov %ax, %es movb $0x14, %cl movw %sp, %si subw %cx, %sp movw %sp, %di cld rep movsb mov %sp, %bp xor %ax, %ax mov %ax, %si main_loop: pop %eax pop %ebx pop %ecx push %ecx push %ebx push %eax cmp $320, %si je hashed64 cmp $240, %si jge phase4 cmp $160, %si jge phase3 cmp $80, %si jge phase2 phase1: //(b&c)|(~b & d) and %eax, %ebx not %eax and %ecx, %eax or %ebx, %eax add $0x5a827999, %eax jmp sharedphase phase2: xor %ebx, %eax xor %ecx, %eax add $0x6ed9eba1, %eax jmp sharedphase phase3: mov %eax, %edx and %ebx, %edx and %ecx, %eax and %ecx, %ebx or %ebx, %eax or %edx, %eax add $0x8f1bbcdc, %eax jmp sharedphase phase4: xor %ebx, %eax xor %ecx, %eax add $0xca62c1d6, %eax sharedphase: // here we have on stack: b,c,d,e,a // f+k in eax mov %bp, %di push %si xor %cx,%cx mov %cx, %ds mov %cx, %es mov %di, %si std mov $4, %cx add $12, %si add $16, %di mov (%di), %ebx rep movsl mov %ebx, (%bp) pop %si movw $(GRUB_BOOT_MACHINE_KERNEL_SEG+0x100), %cx movw %cx, %ds // here we have on stack: b'=a,b,d'=c,e'=d,e // f+k in eax mov (%si), %ecx add %ecx, %eax add 16(%bp), %eax mov (%bp), %ecx mov %ecx, %ebx shl $5, %ecx shr $27, %ebx or %ecx, %ebx add %ebx, %eax mov %eax, 16(%bp) // here we have on stack: b'=a,b,d'=c,e'=d,a' mov 4(%bp), %eax mov %eax, %ebx shl $30, %ebx shr $2, %eax or %ebx, %eax mov %eax, 4(%bp) add $4, %si jmp main_loop hashed64: xorw %ax, %ax movw %ax, %ds movw %ax, %es movw $5, %cx addv: movl (%bp), %eax addl %eax, 20(%bp) addw $4, %bp decw %cx test %cx, %cx jnz addv mov %bp, %sp add $64, ABS(byteshashed) mov ABS(byteshashed), %si cmpw $512, %si jl block32 mov $ABS(hash), %si mov %sp, %di mov $20, %cx cld repe cmpsb self: jnz self ljmp $0, $GRUB_BOOT_MACHINE_KERNEL_ADDR byteshashed: .word 0 . = _start + 0x1a4 hash: .long 0 .long 0 .long 0 .long 0 .long 0 . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC nt_magic: .long 0 .word 0 part_start: . = _start + GRUB_BOOT_MACHINE_PART_START . = _start + GRUB_BOOT_MACHINE_PART_END /* the last 2 bytes in the sector 0 contain the signature */ .word GRUB_BOOT_MACHINE_SIGNATURE