From 7dcd5071e600f8cf48174d1fddb3dba57ec9476d Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 29 May 2019 21:53:48 +0300 Subject: [PATCH] - moved the int86 code out of the 2nd stage boot loader code, and into a new lowcode.s file with its own section (.lowtext) which is placed in low memory alongside the boot loader by the linker (backported from 256boss). --- Makefile | 10 +-- pcboot.ld | 3 + src/boot/boot2.s | 168 +-------------------------------------------------- src/lowcode.s | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 171 deletions(-) create mode 100644 src/lowcode.s diff --git a/Makefile b/Makefile index c4d724a..6887307 100644 --- a/Makefile +++ b/Makefile @@ -38,13 +38,13 @@ pcboot.iso: floppy.img boot.img: bootldr.bin $(bin) cat bootldr.bin $(bin) >$@ -# bootldr.bin will contain only .boot and .boot2 +# bootldr.bin will contain .boot, .boot2, .bootend, and .lowtext bootldr.bin: $(elf) - objcopy -O binary -j '.boot*' $< $@ + objcopy -O binary -j '.boot*' -j .lowtext $< $@ -# the main binary will contain every section *except* .boot and .boot2 +# the main binary will contain every section *except* those $(bin): $(elf) - objcopy -O binary -R '.boot*' $< $@ + objcopy -O binary -R '.boot*' -R .lowtext $< $@ $(elf): $(obj) $(LD) -o $@ $(obj) -Map link.map $(LDFLAGS) @@ -72,7 +72,7 @@ bootldr.disasm: $(elf) objdump -d $< -j .boot -j .boot2 -m i8086 >$@ $(elf).disasm: $(elf) - objdump -d $< -j .startup -j .text -m i386 >$@ + objdump -d $< -j .startup -j .text -j .lowtext -m i386 >$@ $(elf).sym: $(elf) objcopy --only-keep-debug $< $@ diff --git a/pcboot.ld b/pcboot.ld index e2c0308..6a2390f 100644 --- a/pcboot.ld +++ b/pcboot.ld @@ -9,6 +9,9 @@ SECTIONS { /* second stage boot loader */ .boot2 : { * (.boot2); + * (.lowtext); + /* .bootend must stay last */ + * (.bootend); /* pad the boot loader to the next sector boundary */ . = ALIGN(512); } diff --git a/src/boot/boot2.s b/src/boot/boot2.s index 894c7fa..68dffd4 100644 --- a/src/boot/boot2.s +++ b/src/boot/boot2.s @@ -783,177 +783,13 @@ x88_fail: ret + # this part is placed at the very end of all low memory sections + .section .bootend,"ax" .global boot_mem_map_size boot_mem_map_size: .long 0 .global boot_mem_map boot_mem_map: .space 128 - -# this is not boot loader code. It's called later on by the main kernel -# code in 32bit protected mode. It's placed here because it needs to be -# located in base memory as it returns and runs in real mode. - .code32 - .align 4 - # place to save the protected mode IDTR pseudo-descriptor - # with sidt, so that it can be restored before returning - .short 0 -saved_idtr: -idtlim: .short 0 -idtaddr:.long 0 - # real mode IDTR pseudo-descriptor pointing to the IVT at addr 0 - .short 0 -rmidt: .short 0x3ff - .long 0 - -saved_esp: .long 0 -saved_ebp: .long 0 -saved_eax: .long 0 -saved_es: .word 0 -saved_ds: .word 0 -saved_flags: .word 0 -saved_pic1_mask: .byte 0 -saved_pic2_mask: .byte 0 - - # drop back to unreal mode to call 16bit interrupt - .global int86 -int86: - push %ebp - mov %esp, %ebp - pushal - cli - # save protected mode IDTR and replace it with the real mode vectors - sidt (saved_idtr) - lidt (rmidt) - - # save PIC masks - pushl $0 - call get_pic_mask - add $4, %esp - mov %al, saved_pic1_mask - pushl $1 - call get_pic_mask - add $4, %esp - mov %al, saved_pic2_mask - - # modify the int instruction. do this here before the - # cs-load jumps, to let them flush the instruction cache - mov $int_op, %ebx - movb 8(%ebp), %al - movb %al, 1(%ebx) - - # long jump to load code selector for 16bit code (6) - ljmp $0x30,$0f -0: - .code16 - # disable protection - mov %cr0, %eax - and $0xfffe, %ax - mov %eax, %cr0 - # load cs <- 0 - ljmp $0,$0f -0: # zero data segments - xor %ax, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %ss - nop - - # load registers from the int86regs struct - # point esp to the regs struct to load registers with popa/popf - mov %esp, saved_esp - mov %ebp, saved_ebp - mov 12(%ebp), %esp - popal - popfw - pop %es - pop %ds - # ignore fs and gs for now, don't think I'm going to need them - - # move to the real-mode stack, accessible from ss=0 - # just in case the BIOS call screws up our unreal mode - mov $0x7be0, %esp - - # call 16bit interrupt -int_op: int $0 - # BIOS call might have enabled interrupts, cli for good measure - cli - - # save all registers that we'll clobber before having the - # chance to populate the int86regs structure - mov %eax, saved_eax - mov %ds, saved_ds - mov %es, saved_es - pushfw - popw %ax - mov %ax, saved_flags - - # re-enable protection - mov %cr0, %eax - or $1, %ax - mov %eax, %cr0 - # long jump to load code selector for 32bit code (1) - ljmp $0x8,$0f -0: - .code32 - # set data selector (2) to all segment regs - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %ss - nop - - # point the esp to our regs struct, to fill it with pusha/pushf - mov saved_ebp, %ebp - mov 12(%ebp), %esp - add $38, %esp - mov saved_ds, %ax - pushw %ax - mov saved_es, %ax - pushw %ax - # grab the flags and replace the carry bit from the saved flags - pushfw - popw %ax - and $0xfffe, %ax - or saved_flags, %ax - pushw %ax - mov saved_eax, %eax - pushal - mov saved_esp, %esp - - # restore 32bit interrupt descriptor table - lidt (saved_idtr) - - # restore PIC configuration - call init_pic - - # restore IRQ masks - movzbl saved_pic1_mask, %eax - push %eax - pushl $0 - call set_pic_mask - add $8, %esp - - movzbl saved_pic2_mask, %eax - push %eax - pushl $1 - call set_pic_mask - add $8, %esp - - # keyboard voodoo: with some BIOS implementations, after returning from - # int13, there's (I guess) leftover data in the keyboard port and we - # can't receive any more keyboard interrupts afterwards. Reading from - # the keyboard data port (60h) once, seems to resolve this. And it's - # cheap enough, so why not... I give up. - push %eax - in $0x60, %al - pop %eax - - sti - popal - pop %ebp - ret - - .align 4 .global boot_drive_number boot_drive_number: diff --git a/src/lowcode.s b/src/lowcode.s new file mode 100644 index 0000000..67901e4 --- /dev/null +++ b/src/lowcode.s @@ -0,0 +1,178 @@ +# pcboot - bootable PC demo/game kernel +# Copyright (C) 2018-2019 John Tsiombikas +# +# 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 3 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, see . + + .section .lowtext,"ax" + + .code32 + .align 4 + # place to save the protected mode IDTR pseudo-descriptor + # with sidt, so that it can be restored before returning + .short 0 +saved_idtr: +idtlim: .short 0 +idtaddr:.long 0 + # real mode IDTR pseudo-descriptor pointing to the IVT at addr 0 + .short 0 +rmidt: .short 0x3ff + .long 0 + +saved_esp: .long 0 +saved_ebp: .long 0 +saved_eax: .long 0 +saved_es: .word 0 +saved_ds: .word 0 +saved_flags: .word 0 +saved_pic1_mask: .byte 0 +saved_pic2_mask: .byte 0 + + # drop back to unreal mode to call 16bit interrupt + .global int86 +int86: + push %ebp + mov %esp, %ebp + pushal + cli + # save protected mode IDTR and replace it with the real mode vectors + sidt (saved_idtr) + lidt (rmidt) + + # save PIC masks + pushl $0 + call get_pic_mask + add $4, %esp + mov %al, saved_pic1_mask + pushl $1 + call get_pic_mask + add $4, %esp + mov %al, saved_pic2_mask + + # modify the int instruction. do this here before the + # cs-load jumps, to let them flush the instruction cache + mov $int_op, %ebx + movb 8(%ebp), %al + movb %al, 1(%ebx) + + # long jump to load code selector for 16bit code (6) + ljmp $0x30,$0f +0: + .code16 + # disable protection + mov %cr0, %eax + and $0xfffe, %ax + mov %eax, %cr0 + # load cs <- 0 + ljmp $0,$0f +0: # zero data segments + xor %ax, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + nop + + # load registers from the int86regs struct + # point esp to the regs struct to load registers with popa/popf + mov %esp, saved_esp + mov %ebp, saved_ebp + mov 12(%ebp), %esp + popal + popfw + pop %es + pop %ds + # ignore fs and gs for now, don't think I'm going to need them + + # move to the real-mode stack, accessible from ss=0 + # just in case the BIOS call screws up our unreal mode + mov $0x7be0, %esp + + # call 16bit interrupt +int_op: int $0 + # BIOS call might have enabled interrupts, cli for good measure + cli + + # save all registers that we'll clobber before having the + # chance to populate the int86regs structure + mov %eax, saved_eax + mov %ds, saved_ds + mov %es, saved_es + pushfw + popw %ax + mov %ax, saved_flags + + # re-enable protection + mov %cr0, %eax + or $1, %ax + mov %eax, %cr0 + # long jump to load code selector for 32bit code (1) + ljmp $0x8,$0f +0: + .code32 + # set data selector (2) to all segment regs + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + nop + + # point the esp to our regs struct, to fill it with pusha/pushf + mov saved_ebp, %ebp + mov 12(%ebp), %esp + add $38, %esp + mov saved_ds, %ax + pushw %ax + mov saved_es, %ax + pushw %ax + # grab the flags and replace the carry bit from the saved flags + pushfw + popw %ax + and $0xfffe, %ax + or saved_flags, %ax + pushw %ax + mov saved_eax, %eax + pushal + mov saved_esp, %esp + + # restore 32bit interrupt descriptor table + lidt (saved_idtr) + + # restore PIC configuration + call init_pic + + # restore IRQ masks + movzbl saved_pic1_mask, %eax + push %eax + pushl $0 + call set_pic_mask + add $8, %esp + + movzbl saved_pic2_mask, %eax + push %eax + pushl $1 + call set_pic_mask + add $8, %esp + + # keyboard voodoo: with some BIOS implementations, after returning from + # int13, there's (I guess) leftover data in the keyboard port and we + # can't receive any more keyboard interrupts afterwards. Reading from + # the keyboard data port (60h) once, seems to resolve this. And it's + # cheap enough, so why not... I give up. + push %eax + in $0x60, %al + pop %eax + + sti + popal + pop %ebp + ret -- 1.7.10.4