switch video mode hack by dropping to real mode to call the video bios works!
authorJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 27 Apr 2018 09:01:03 +0000 (12:01 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 27 Apr 2018 09:01:03 +0000 (12:01 +0300)
src/boot/boot2.s
src/segm.c
src/segm.h
src/startup.s
src/vbioshack.s [deleted file]

index 59918b8..37f1026 100644 (file)
@@ -553,5 +553,76 @@ kbc_wait_write:
 
 numbuf: .space 16
 
+
+# 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 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
+
+       # drop back to unreal mode to set video mode
+       .global set_mode13h
+set_mode13h:
+       pushal
+       cli
+       # save protected mode IDTR and replace it with the real mode vectors
+       sidt (saved_idtr)
+       lidt (rmidt)
+
+       # 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
+
+       # switch video mode by calling the video bios
+       mov $0x13, %ax
+       int $0x10
+
+       # 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
+
+       # restore 32bit interrupt descriptor table
+       lidt (saved_idtr)
+       sti
+       popal
+       ret
+
+
+       # buffer used by the track loader ... to load tracks.
        .align 16
 buffer:
index 6fede17..c6baffd 100644 (file)
@@ -43,6 +43,7 @@ enum {TYPE_DATA, TYPE_CODE};
 #define TSS_TYPE_BITS  (9 << 8)
 
 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
+static void segm_desc16(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl);
 
 /* these functions are implemented in segm-asm.S */
@@ -52,7 +53,7 @@ void set_task_reg(uint16_t tss_selector);
 
 
 /* our global descriptor table */
-static desc_t gdt[6] __attribute__((aligned(8)));
+static desc_t gdt[NUM_SEGMENTS] __attribute__((aligned(8)));
 
 
 void init_segm(void)
@@ -62,6 +63,7 @@ void init_segm(void)
        segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA);
        segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE);
        segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA);
+       segm_desc16(gdt + SEGM_CODE16, 0, 0xffff, 0, TYPE_CODE);
 
        set_gdt((uint32_t)gdt, sizeof gdt - 1);
 
@@ -98,6 +100,22 @@ static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int
        desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG;
 }
 
+static void segm_desc16(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type)
+{
+       desc->d[0] = limit & 0xffff; /* low order 16bits of limit */
+       desc->d[1] = base & 0xffff;  /* low order 16bits of base */
+
+       /* third 16bit part contains the last 8 bits of base, the 2 priviledge
+        * level bits starting on bit 13, present flag on bit 15, and type bits
+        * starting from bit 8
+        */
+       desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
+               BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE));
+
+       /* 16bit descriptors have the upper word 0 */
+       desc->d[3] = 0;
+}
+
 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl)
 {
        desc->d[0] = limit & 0xffff;
index 59f8fc4..b57375b 100644 (file)
@@ -18,19 +18,22 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #ifndef SEGM_H_
 #define SEGM_H_
 
-#define SEGM_KCODE     1
-#define SEGM_KDATA     2
-#define SEGM_UCODE     3
-#define SEGM_UDATA     4
-#define SEGM_TASK      5
+enum {
+       SEGM_KCODE = 1,
+       SEGM_KDATA = 2,
+       SEGM_UCODE,
+       SEGM_UDATA,
+       SEGM_TASK,
+       SEGM_CODE16,
+
+       NUM_SEGMENTS
+};
 
-#ifndef ASM
 void init_segm(void);
 
 uint16_t selector(int idx, int rpl);
 
 void set_tss(uint32_t addr);
-#endif /* ASM */
 
 
 #endif /* SEGM_H_ */
index 82f548e..8041c13 100644 (file)
@@ -21,6 +21,9 @@
        .extern _bss_end
        .extern pcboot_main
 
+       # move the stack to the top of the conventional memory
+       movl $0x80000, %esp
+
        # zero the BSS section
        xor %eax, %eax
        mov $_bss_start, %edi
diff --git a/src/vbioshack.s b/src/vbioshack.s
deleted file mode 100644 (file)
index 66ffa78..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# pcboot - bootable PC demo/game kernel
-# Copyright (C) 2018  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/>.
-
-       .text
-
-       .align 4
-       .short 0
-saved_idtr:
-idtlim:        .short 0
-idtaddr:.long 0
-
-       .short 0
-saved_gdtr:
-gdtlim:        .short 0
-gdtaddr:.long 0
-
-       .short 0
-rmidt: .short 0x3ff
-       .long 0
-
-       # drop back to real mode to set video mode hack
-       .global set_mode13h
-set_mode13h:
-       cli
-       #sgdt (saved_gdtr)
-       sidt (saved_idtr)
-       lidt (rmidt)
-
-       mov %cr0, %eax
-       and $0xfffe, %ax
-       mov %eax, %cr0
-       jmp 0f
-
-0:     xor %ax, %ax
-       mov %ax, %ds
-       mov %ax, %es
-       mov %ax, %ss
-
-       #mov $0x13, %ax
-       #int $0x10
-
-       mov %cr0, %eax
-       or $1, %ax
-       mov %eax, %cr0
-       jmp 0f
-
-0:     mov $0x10, %ax
-       mov %ax, %ds
-       mov %ax, %es
-       mov %ax, %ss
-
-       sidt (saved_idtr)
-       sti
-       ret