/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2016 Toomas Soome <tsoome@me.com>
*/
/*
* Relocate is needed to support loading code which has to be located
* below 1MB, as both BTX and loader are using low memory area.
*
* Relocate and start loaded code. Since loaded code may need to be
* placed in an already occupied memory area, the code is moved to a safe
* memory area and then btx __exec will be called with physical pointer
* to this area. __exec will set the pointer to %eax and call *%eax,
* so that on entry, we have the new "base" address in %eax.
*
* Relocate will first set up and load new safe GDT to shut down BTX,
* then loaded code will be relocated to final memory location,
* then machine will be switched from 32-bit protected mode to 16-bit
* protected mode following by switch to real mode with A20 enabled or
* disabled. Finally the loaded code will be started and it will take
* over the whole system.
*
* For now, the known "safe" memory area for relocate is 0x600,
* the actual "free" memory is supposed to start from 0x500, leaving
* first 0x100 bytes in reserve. As relocate code+data is very small,
* it will leave enough space to set up boot blocks to 0:7c00 or load
* linux kernel below 1MB space.
*/
/*
* segment selectors
*/
.p2align 4
/*
* set up GDT from new location
*/
relocater.1:
/* set up jump */
/* set up gdt */
/* load gdt */
/* update cs */
relocater.2:
/*
* relocate data loop. load source, dest and size from
* relocater_data[i], 0 value will stop the loop.
* registers used for move: %esi, %edi, %ecx.
* %ebx to keep base
* %edx for relocater_data offset
*/
loop.1:
loop.2:
/*
* data is relocated, switch to 16-bit mode
*/
relocater.3:
/* clear PE */
relocater.4:
/*
* set real mode irq offsets
*/
# done
/*
* Should A20 be left enabled?
*/
/* movw imm16, %ax */
.byte 0xb8
.word 0
/* Disable A20 */
int $0x15
inb $0x92
outb $0x92
1:
loop 1b
/*
* set up registers
*/
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm16, %ax. */
.byte 0xb8
/* movw imm32, %eax. */
relocator_esi: .long 0
/* movw imm32, %edx. */
relocator_edx: .long 0
/* movw imm32, %ebx. */
relocator_ebx: .long 0
/* movw imm32, %eax. */
relocator_eax: .long 0
/* movw imm32, %ebp. */
relocator_ebp: .long 0
.word 0
.word 0
/* GDT to reset BTX */
.p2align 4
jump_vector: .long 0
.long SEL_SCODE
gdt.1:
.long 0
/* reserve space for 3 entries */
.long 0 /* src */
.long 0 /* dest */
.long 0 /* size */
.long 0 /* src */
.long 0 /* dest */
.long 0 /* size */
.long 0 /* src */
.long 0 /* dest */
.long 0 /* size */
.long 0
.long relocater_size-relocater