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:
#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 */
/* 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)
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);
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;
+++ /dev/null
-# 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