- moved the int86 code out of the 2nd stage boot loader code, and into a
authorJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 29 May 2019 18:53:48 +0000 (21:53 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 29 May 2019 18:53:48 +0000 (21:53 +0300)
  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
pcboot.ld
src/boot/boot2.s
src/lowcode.s [new file with mode: 0644]

index c4d724a..6887307 100644 (file)
--- 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 $< $@
index e2c0308..6a2390f 100644 (file)
--- 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);
        }
index 894c7fa..68dffd4 100644 (file)
@@ -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 (file)
index 0000000..67901e4
--- /dev/null
@@ -0,0 +1,178 @@
+# pcboot - bootable PC demo/game kernel
+# Copyright (C) 2018-2019  John Tsiombikas <nuclear@member.fsf.org>
+#
+# 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 <https://www.gnu.org/licenses/>.
+
+       .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