| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 2000 Free Software Foundation, Inc. |
| * |
| * This program 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 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program 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 this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| #include <nbi.h> |
| #include <diskless_size.h> |
| |
| .file "nbloader.S" |
| .text |
| .code16 |
| |
| /* Just a dummy entry */ |
| .globl _start; _start: |
| |
| /* |
| * netboot image header |
| */ |
| |
| .long NBI_MAGIC |
| .long 0x00000004 |
| /* load address of the first block */ |
| .word NBI_DEST_OFF |
| .word NBI_DEST_SEG |
| /* start addr of the relocation code */ |
| .word NBI_DEST_OFF + (relocate - _start) |
| .word NBI_DEST_SEG |
| |
| .long 0x04000004 |
| .long NBI_DEST_ADDR + 0x0200 |
| .long DISKLESS_SIZE |
| .long DISKLESS_SIZE |
| |
| relocate: |
| /* |
| * This code is for now located at 0x10000. |
| * Relocate the code in two steps: |
| * 1. Copy the first 32k to 0x8000 and jump to the relocated area. |
| * 2. Copy the rest to 0x10000 (0x8000 + 32k). |
| */ |
| |
| /* Copy the first 32k */ |
| movw $NBI_DEST_SEG, %ax |
| movw %ax, %ds |
| movw $RELOCATED_SEG, %ax |
| movw %ax, %es |
| xorw %si, %si |
| xorw %di, %di |
| /* Always copy 32k bytes */ |
| movw $0x4000, %cx |
| |
| cld |
| rep |
| movsw |
| |
| /* Jump to the relocated address */ |
| ljmp $0, $(RELOCATED_ADDR + copy_rest - _start) |
| |
| /* Copy the rest */ |
| copy_rest: |
| /* Set %edx to the number of bytes */ |
| movl $(DISKLESS_SIZE + 0x200 - 0x8000), %edx |
| |
| copy_loop: |
| /* Check the rest */ |
| orl %edx, %edx |
| jz boot_stage2 |
| |
| /* Copy by 32k, as that is easy to implement */ |
| movl $0x8000, %ecx |
| cmpl %ecx, %edx |
| jg copy |
| movl %edx, %ecx |
| |
| copy: |
| /* Update the number of rest bytes */ |
| subl %ecx, %edx |
| |
| /* Add 0x0800 (32k >> 4) into %es and %ds */ |
| movw %es, %ax |
| addw $0x0800, %ax |
| movw %ax, %es |
| movw %ds, %ax |
| addw $0x800, %ax |
| movw %ax, %ds |
| |
| /* Zero the offsets */ |
| xorw %si, %si |
| xorw %di, %di |
| |
| /* Use word-size copy */ |
| addw $1, %cx |
| shrw $1, %cx |
| |
| /* The direction is already correct */ |
| rep |
| movsw |
| |
| jmp copy_loop |
| |
| /* Jump to the stage2 */ |
| boot_stage2: |
| ljmp $0, $STAGE2_START_ADDR |
| |
| /* This ensures that the length of this image will be 1 sector */ |
| . = _start + 0x200 - 1 |
| .byte 0 |