From 4c7af0d72e32cc07c04345bc9fe57a4a32a29695 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Fri, 27 Apr 2018 12:01:03 +0300 Subject: [PATCH] switch video mode hack by dropping to real mode to call the video bios works! --- src/boot/boot2.s | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/segm.c | 20 ++++++++++++++- src/segm.h | 17 +++++++------ src/startup.s | 3 +++ src/vbioshack.s | 67 --------------------------------------------------- 5 files changed, 103 insertions(+), 75 deletions(-) delete mode 100644 src/vbioshack.s diff --git a/src/boot/boot2.s b/src/boot/boot2.s index 59918b8..37f1026 100644 --- a/src/boot/boot2.s +++ b/src/boot/boot2.s @@ -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: diff --git a/src/segm.c b/src/segm.c index 6fede17..c6baffd 100644 --- a/src/segm.c +++ b/src/segm.c @@ -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; diff --git a/src/segm.h b/src/segm.h index 59f8fc4..b57375b 100644 --- a/src/segm.h +++ b/src/segm.h @@ -18,19 +18,22 @@ along with this program. If not, see . #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_ */ diff --git a/src/startup.s b/src/startup.s index 82f548e..8041c13 100644 --- a/src/startup.s +++ b/src/startup.s @@ -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 index 66ffa78..0000000 --- a/src/vbioshack.s +++ /dev/null @@ -1,67 +0,0 @@ -# pcboot - bootable PC demo/game kernel -# Copyright (C) 2018 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 . - - .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 -- 1.7.10.4