Path: blob/main/stand/i386/libi386/relocater_tramp.S
34860 views
/*-1* Copyright 2015 Toomas Soome <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/252627/*28* relocate is needed to support loading code which has to be located29* below 1MB, as both BTX and loader are using low memory area.30*31* relocate and start loaded code. Since loaded code may need to be32* placed to already occupied memory area, this code is moved to safe33* memory area and then btx __exec will be called with physical pointer34* to this area. __exec will set pointer to %eax and use call *%eax,35* so on entry, we have new "base" address in %eax.36*37* Relocate will first set up and load new safe GDT to shut down BTX,38* then loaded code will be relocated to final memory location,39* then machine will be switched from 32bit protected mode to 16bit40* protected mode following by switch to real mode with A20 enabled or41* disabled. Finally the loaded code will be started and it will take42* over the whole system.43*44* For now, the known "safe" memory area for relocate is 0x600,45* the actual "free" memory is supposed to start from 0x500, leaving46* first 0x100 bytes in reserve. As relocate code+data is very small,47* it will leave enough space to set up boot blocks to 0:7c00 or load48* linux kernel below 1MB space.49*/50/*51* segment selectors52*/53.set SEL_SCODE,0x854.set SEL_SDATA,0x1055.set SEL_RCODE,0x1856.set SEL_RDATA,0x205758.p2align 459.globl relocater60relocater:61cli62/*63* set up GDT from new location64*/65movl %eax, %esi /* our base address */66add $(relocater.1-relocater), %eax67jmp *%eax68relocater.1:69/* set up jump */70lea (relocater.2-relocater)(%esi), %eax71movl %eax, (jump_vector-relocater) (%esi)7273/* set up gdt */74lea (gdt-relocater) (%esi), %eax75movl %eax, (gdtaddr-relocater) (%esi)7677/* load gdt */78lgdt (gdtdesc - relocater) (%esi)79lidt (idt-relocater) (%esi)8081/* update cs */82ljmp *(jump_vector-relocater) (%esi)8384.code3285relocater.2:86xorl %eax, %eax87movb $SEL_SDATA, %al88movw %ax, %ss89movw %ax, %ds90movw %ax, %es91movw %ax, %fs92movw %ax, %gs93movl %cr0, %eax /* disable paging */94andl $~0x80000000,%eax95movl %eax, %cr096xorl %ecx, %ecx /* flush TLB */97movl %ecx, %cr398cld99/*100* relocate data loop. load source, dest and size from101* relocater_data[i], 0 value will stop the loop.102* registers used for move: %esi, %edi, %ecx.103* %ebx to keep base104* %edx for relocater_data offset105*/106movl %esi, %ebx /* base address */107xorl %edx, %edx108loop.1:109movl (relocater_data-relocater)(%ebx, %edx, 4), %eax110testl %eax, %eax111jz loop.2112movl (relocater_data-relocater)(%ebx, %edx, 4), %esi113inc %edx114movl (relocater_data-relocater)(%ebx, %edx, 4), %edi115inc %edx116movl (relocater_data-relocater)(%ebx, %edx, 4), %ecx117inc %edx118rep119movsb120jmp loop.1121loop.2:122movl %ebx, %esi /* restore esi */123/*124* data is relocated, switch to 16bit mode125*/126lea (relocater.3-relocater)(%esi), %eax127movl %eax, (jump_vector-relocater) (%esi)128movl $SEL_RCODE, %eax129movl %eax, (jump_vector-relocater+4) (%esi)130131ljmp *(jump_vector-relocater) (%esi)132relocater.3:133.code16134135movw $SEL_RDATA, %ax136movw %ax, %ds137movw %ax, %es138movw %ax, %fs139movw %ax, %gs140movw %ax, %ss141lidt (idt-relocater) (%esi)142lea (relocater.4-relocater)(%esi), %eax143movl %eax, (jump_vector-relocater) (%esi)144xorl %eax, %eax145movl %eax, (jump_vector-relocater+4) (%esi)146/* clear PE */147movl %cr0, %eax148dec %al149movl %eax, %cr0150ljmp *(jump_vector-relocater) (%esi)151relocater.4:152xorw %ax, %ax153movw %ax, %ds154movw %ax, %es155movw %ax, %fs156movw %ax, %gs157movw %ax, %ss158/*159* set real mode irq offsets160*/161movw $0x7008,%bx162in $0x21,%al # Save master163push %ax # IMR164in $0xa1,%al # Save slave165push %ax # IMR166movb $0x11,%al # ICW1 to167outb %al,$0x20 # master,168outb %al,$0xa0 # slave169movb %bl,%al # ICW2 to170outb %al,$0x21 # master171movb %bh,%al # ICW2 to172outb %al,$0xa1 # slave173movb $0x4,%al # ICW3 to174outb %al,$0x21 # master175movb $0x2,%al # ICW3 to176outb %al,$0xa1 # slave177movb $0x1,%al # ICW4 to178outb %al,$0x21 # master,179outb %al,$0xa1 # slave180pop %ax # Restore slave181outb %al,$0xa1 # IMR182pop %ax # Restore master183outb %al,$0x21 # IMR184# done185/*186* Should A20 be left enabled?187*/188/* movw imm16, %ax */189.byte 0xb8190.globl relocator_a20_enabled191relocator_a20_enabled:192.word 0193test %ax, %ax194jnz a20_done195196movw $0xa00, %ax197movw %ax, %sp198movw %ax, %bp199200/* Disable A20 */201movw $0x2400, %ax202int $0x15203# jnc a20_done204205call a20_check_state206testb %al, %al207jz a20_done208209inb $0x92210andb $(~0x03), %al211outb $0x92212jmp a20_done213214a20_check_state:215movw $100, %cx2161:217xorw %ax, %ax218movw %ax, %ds219decw %ax220movw %ax, %es221xorw %ax, %ax222movw $0x8000, %ax223movw %ax, %si224addw $0x10, %ax225movw %ax, %di226movb %ds:(%si), %dl227movb %es:(%di), %al228movb %al, %dh229decb %dh230movb %dh, %ds:(%si)231outb %al, $0x80232outb %al, $0x80233movb %es:(%di), %dh234subb %dh, %al235xorb $1, %al236movb %dl, %ds:(%si)237testb %al, %al238jz a20_done239loop 1b240ret241a20_done:242/*243* set up registers244*/245/* movw imm16, %ax. */246.byte 0xb8247.globl relocator_ds248relocator_ds: .word 0249movw %ax, %ds250251/* movw imm16, %ax. */252.byte 0xb8253.globl relocator_es254relocator_es: .word 0255movw %ax, %es256257/* movw imm16, %ax. */258.byte 0xb8259.globl relocator_fs260relocator_fs: .word 0261movw %ax, %fs262263/* movw imm16, %ax. */264.byte 0xb8265.globl relocator_gs266relocator_gs: .word 0267movw %ax, %gs268269/* movw imm16, %ax. */270.byte 0xb8271.globl relocator_ss272relocator_ss: .word 0273movw %ax, %ss274275/* movw imm16, %ax. */276.byte 0xb8277.globl relocator_sp278relocator_sp: .word 0279movzwl %ax, %esp280281/* movw imm32, %eax. */282.byte 0x66, 0xb8283.globl relocator_esi284relocator_esi: .long 0285movl %eax, %esi286287/* movw imm32, %edx. */288.byte 0x66, 0xba289.globl relocator_edx290relocator_edx: .long 0291292/* movw imm32, %ebx. */293.byte 0x66, 0xbb294.globl relocator_ebx295relocator_ebx: .long 0296297/* movw imm32, %eax. */298.byte 0x66, 0xb8299.globl relocator_eax300relocator_eax: .long 0301302/* movw imm32, %ebp. */303.byte 0x66, 0xbd304.globl relocator_ebp305relocator_ebp: .long 0306307sti308.byte 0xea /* ljmp */309.globl relocator_ip310relocator_ip:311.word 0312.globl relocator_cs313relocator_cs:314.word 0315316/* GDT to reset BTX */317.code32318.p2align 4319jump_vector: .long 0320.long SEL_SCODE321322gdt: .word 0x0, 0x0 /* null entry */323.byte 0x0, 0x0, 0x0, 0x0324.word 0xffff, 0x0 /* SEL_SCODE */325.byte 0x0, 0x9a, 0xcf, 0x0326.word 0xffff, 0x0 /* SEL_SDATA */327.byte 0x0, 0x92, 0xcf, 0x0328.word 0xffff, 0x0 /* SEL_RCODE */329.byte 0x0, 0x9a, 0x0f, 0x0330.word 0xffff, 0x0 /* SEL_RDATA */331.byte 0x0, 0x92, 0x0f, 0x0332gdt.1:333334gdtdesc: .word gdt.1 - gdt - 1 /* limit */335gdtaddr: .long 0 /* base */336337idt: .word 0x3ff338.long 0339340.globl relocater_data341relocater_data:342.long 0 /* src */343.long 0 /* dest */344.long 0 /* size */345.long 0 /* src */346.long 0 /* dest */347.long 0 /* size */348.long 0 /* src */349.long 0 /* dest */350.long 0 /* size */351.long 0352353.globl relocater_size354relocater_size:355.long relocater_size-relocater356357358