├── init
├── obj
│ └── .content
├── src
│ ├── start.asm
│ └── init.bas
├── init.ld
└── Makefile
├── drivers
├── pci
│ ├── .content
│ ├── obj
│ │ └── .content
│ ├── src
│ │ ├── start.asm
│ │ └── main.bas
│ ├── pci.ld
│ └── Makefile
├── bochsvga
│ ├── obj
│ │ └── .content
│ ├── src
│ │ └── start.asm
│ ├── bochsvga.ld
│ └── Makefile
├── keyboard
│ ├── obj
│ │ └── .content
│ ├── src
│ │ ├── start.asm
│ │ ├── keyboard.bi
│ │ ├── sc2kc.bas
│ │ └── main.bas
│ ├── keyboard.ld
│ └── Makefile
└── vgaconsole
│ ├── obj
│ └── .content
│ ├── src
│ ├── start.asm
│ └── main.bas
│ ├── vgaconsole.ld
│ └── Makefile
├── kernel
├── obj
│ └── .content
├── asl.txt
├── kernel.ld
├── include
│ ├── pit.bi
│ ├── idt.bi
│ ├── in_out.bi
│ ├── syscall.bi
│ ├── kmm.bi
│ ├── modules.bi
│ ├── mem.bi
│ ├── elf.bi
│ ├── pic.bi
│ ├── string_tokenizer.bi
│ ├── spinlock.bi
│ ├── interrupt.bi
│ ├── zstring.bi
│ ├── interrupt_handler.bi
│ ├── kernel.bi
│ ├── io_man.bi
│ ├── syscall_defs.bi
│ ├── debug.bi
│ ├── cpu.bi
│ ├── apic.bi
│ ├── isf.bi
│ ├── atomic.bi
│ ├── uid128.bi
│ ├── acpi.bi
│ ├── panic.bi
│ ├── video.bi
│ ├── pmm.bi
│ ├── address_space.bi
│ ├── gdt.bi
│ ├── process.bi
│ ├── smp.bi
│ ├── vfs.bi
│ ├── refcount_smartptr.bi
│ ├── thread.bi
│ ├── vmm.bi
│ ├── intrusive_list.bi
│ └── elf32.bi
├── Makefile
└── src
│ ├── pit.bas
│ ├── arch
│ ├── x64
│ │ └── atomic_arch.bas
│ ├── x86
│ │ ├── atomic_arch.bas
│ │ ├── start.asm
│ │ ├── trampoline.asm.embedd
│ │ └── gdt.bas
│ └── arm
│ │ └── start.S
│ ├── in_out.bas
│ ├── assert.bas
│ ├── mem.bas
│ ├── atomic.bas
│ ├── uid128.bas
│ ├── spinlock.bas
│ ├── cpu.bas
│ ├── string_tokenizer.bas
│ ├── zstring.bas
│ ├── pmm_dma24.bas
│ ├── process.bas
│ ├── pic.bas
│ ├── pmm_normal.bas
│ ├── debug.bas
│ ├── io_man.bas
│ ├── stubs.asm
│ ├── interrupt.bas
│ ├── address_space.bas
│ ├── modules.bas
│ ├── elf.bas
│ ├── lapic.bas
│ ├── interrupt_handler.bas
│ ├── panic.bas
│ ├── vfs.bas
│ ├── main.bas
│ ├── pmm.bas
│ ├── smp.bas
│ └── thread.bas
├── libfrost
├── obj
│ └── .content
├── src
│ ├── 43.bas
│ ├── memory.bas
│ ├── io_ports.bas
│ ├── irq_handling.bas
│ ├── process.bas
│ ├── ipc.bas
│ ├── vfs.bas
│ ├── thread.bas
│ └── libfrost_internal.bi
├── Makefile
└── frost.bi
├── .gitignore
├── doc
└── gpl-3.0.odt
└── README.md
/init/obj/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/drivers/pci/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/drivers/pci/obj/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/kernel/obj/.content:
--------------------------------------------------------------------------------
1 | # the kernels object files will go here
--------------------------------------------------------------------------------
/libfrost/obj/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/drivers/bochsvga/obj/.content:
--------------------------------------------------------------------------------
1 | # object files will go here
2 |
--------------------------------------------------------------------------------
/drivers/keyboard/obj/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iso
2 | *.krn
3 | *.elf
4 | *.obj
5 | *.o
6 | *.a
7 |
--------------------------------------------------------------------------------
/drivers/vgaconsole/obj/.content:
--------------------------------------------------------------------------------
1 | # init's object files will go here
--------------------------------------------------------------------------------
/doc/gpl-3.0.odt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thrimbor/frost/HEAD/doc/gpl-3.0.odt
--------------------------------------------------------------------------------
/drivers/bochsvga/src/start.asm:
--------------------------------------------------------------------------------
1 | extern MAIN
2 | global _start
3 |
4 | section .text
5 | _start:
6 | call MAIN
7 | jmp $
8 |
--------------------------------------------------------------------------------
/drivers/keyboard/src/start.asm:
--------------------------------------------------------------------------------
1 | extern MAIN
2 | global _start
3 |
4 | section .text
5 | _start:
6 | call MAIN
7 | jmp $
8 |
--------------------------------------------------------------------------------
/drivers/keyboard/src/keyboard.bi:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | declare function scancode_to_keycode (set as integer, scancode as ushort) as ubyte
4 |
--------------------------------------------------------------------------------
/libfrost/src/43.bas:
--------------------------------------------------------------------------------
1 | #include "libfrost_internal.bi"
2 |
3 | sub frost_syscall_43 (str_ptr as byte ptr)
4 | syscall_param1(43, str_ptr)
5 | end sub
6 |
--------------------------------------------------------------------------------
/drivers/pci/src/start.asm:
--------------------------------------------------------------------------------
1 | extern fb_ctor__main
2 | global _start
3 |
4 | section .text
5 | _start:
6 | mov esp, stack
7 | call fb_ctor__main
8 | jmp $
9 |
10 | section .bss
11 | resb 4096
12 | stack:
13 |
--------------------------------------------------------------------------------
/drivers/vgaconsole/src/start.asm:
--------------------------------------------------------------------------------
1 | extern fb_ctor__main
2 | global _start
3 |
4 | section .text
5 | _start:
6 | mov esp, stack
7 | call fb_ctor__main
8 | jmp $
9 |
10 | section .bss
11 | resb 4096
12 | stack:
13 |
--------------------------------------------------------------------------------
/init/src/start.asm:
--------------------------------------------------------------------------------
1 | ;extern fb_ctor__init
2 | ;global _start
3 |
4 | ;section .text
5 | ;_start:
6 | ; call fb_ctor__init
7 | ; jmp $
8 |
9 | extern MAIN
10 | extern THREADFUNC
11 | global _start
12 |
13 | section .text
14 | _start:
15 | call MAIN
16 | jmp $
17 |
18 |
--------------------------------------------------------------------------------
/init/init.ld:
--------------------------------------------------------------------------------
1 | ENTRY(_start)
2 |
3 | SECTIONS
4 | {
5 | . = 0x40000000;
6 |
7 | .text : {
8 | *(.text)
9 | }
10 | .data ALIGN(4096) : {
11 | *(.data)
12 | }
13 | .rodata ALIGN(4096) : {
14 | *(.rodata)
15 | }
16 | .bss ALIGN(4096) : {
17 | *(.bss)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/drivers/pci/pci.ld:
--------------------------------------------------------------------------------
1 | ENTRY(_start)
2 |
3 | SECTIONS
4 | {
5 | . = 0x40000000;
6 |
7 | .text : {
8 | *(.text)
9 | }
10 | .data ALIGN(4096) : {
11 | *(.data)
12 | }
13 | .rodata ALIGN(4096) : {
14 | *(.rodata)
15 | }
16 | .bss ALIGN(4096) : {
17 | *(.bss)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/drivers/bochsvga/bochsvga.ld:
--------------------------------------------------------------------------------
1 | ENTRY(_start)
2 |
3 | SECTIONS
4 | {
5 | . = 0x40000000;
6 |
7 | .text : {
8 | *(.text)
9 | }
10 | .data ALIGN(4096) : {
11 | *(.data)
12 | }
13 | .rodata ALIGN(4096) : {
14 | *(.rodata)
15 | }
16 | .bss ALIGN(4096) : {
17 | *(.bss)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/drivers/keyboard/keyboard.ld:
--------------------------------------------------------------------------------
1 | ENTRY(_start)
2 |
3 | SECTIONS
4 | {
5 | . = 0x40000000;
6 |
7 | .text : {
8 | *(.text)
9 | }
10 | .data ALIGN(4096) : {
11 | *(.data)
12 | }
13 | .rodata ALIGN(4096) : {
14 | *(.rodata)
15 | }
16 | .bss ALIGN(4096) : {
17 | *(.bss)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/drivers/vgaconsole/vgaconsole.ld:
--------------------------------------------------------------------------------
1 | ENTRY(_start)
2 |
3 | SECTIONS
4 | {
5 | . = 0x40000000;
6 |
7 | .text : {
8 | *(.text)
9 | }
10 | .data ALIGN(4096) : {
11 | *(.data)
12 | }
13 | .rodata ALIGN(4096) : {
14 | *(.rodata)
15 | }
16 | .bss ALIGN(4096) : {
17 | *(.bss)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/libfrost/src/memory.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | function frost_syscall_memory_allocate_physical (bytes as uinteger, addr as any ptr) as any ptr
5 | syscall_param2_ret(SYSCALL_MEMORY_ALLOCATE_PHYSICAL, function, bytes, addr)
6 | end function
7 |
--------------------------------------------------------------------------------
/libfrost/src/io_ports.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | sub frost_syscall_port_request (port as uinteger)
5 | syscall_param1(SYSCALL_PORT_REQUEST, port)
6 | end sub
7 |
8 | sub frost_syscall_port_release (port as uinteger)
9 | syscall_param1(SYSCALL_PORT_RELEASE, port)
10 | end sub
11 |
--------------------------------------------------------------------------------
/kernel/asl.txt:
--------------------------------------------------------------------------------
1 | virtual address space layout:
2 |
3 | 0x00000000 - 0x000FFFFF - undefined stuff
4 | 0x00100000 - kernel_end_label - kernel code
5 | 0x10000000 - 0x10100000 - kernel heap
6 | 0x3F800000 - 0x3FBFFFFF - page stack (grows downwards)
7 | 0x3FC00000 - 0x3FFFFFFF - page tables of the current process
8 |
9 | 0x40000000 - 0xFFFFFFFF - userspace
10 |
--------------------------------------------------------------------------------
/libfrost/src/irq_handling.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | sub frost_syscall_irq_handler_register (irq as uinteger, handler as any ptr)
5 | syscall_param2(SYSCALL_IRQ_HANDLER_REGISTER, irq, handler)
6 | end sub
7 |
8 | sub frost_syscall_irq_handler_exit (irq as uinteger)
9 | syscall_param1(SYSCALL_IRQ_HANDLER_EXIT, irq)
10 | end sub
11 |
--------------------------------------------------------------------------------
/libfrost/src/process.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | function frost_syscall_process_get_pid () as uinteger
5 | syscall_param0_ret(SYSCALL_PROCESS_GET_PID, function)
6 | end function
7 |
8 | function frost_syscall_get_parent_pid () as uinteger
9 | syscall_param0_ret(SYSCALL_PROCESS_GET_PARENT_PID, function)
10 | end function
11 |
12 |
13 |
--------------------------------------------------------------------------------
/libfrost/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
3 |
4 | COMPILER = fbc
5 | AR = ar
6 |
7 | CFLAGS = -c -nodeflibs -lang fb -arch 486
8 | ARFLAGS = -cvq
9 |
10 | libfrost.a: $(OBJS)
11 | $(AR) $(ARFLAGS) $@ $^
12 |
13 | obj/%.o: src/%.bas
14 | $(COMPILER) $(CFLAGS) $^ -o $@
15 |
16 | clean:
17 | rm -f $(OBJS) libfrost.a
18 |
19 | .PHONY: clean
20 |
--------------------------------------------------------------------------------
/libfrost/src/ipc.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | sub frost_syscall_ipc_handler_call (pid as uinteger)
5 | syscall_param1(SYSCALL_IPC_HANDLER_CALL, pid)
6 | end sub
7 |
8 | sub frost_syscall_ipc_handler_set (handler as any ptr)
9 | syscall_param1(SYSCALL_IPC_HANDLER_SET, handler)
10 | end sub
11 |
12 | sub frost_syscall_ipc_handler_exit ()
13 | syscall_param0(SYSCALL_IPC_HANDLER_EXIT)
14 | end sub
15 |
--------------------------------------------------------------------------------
/libfrost/src/vfs.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | sub frost_syscall_vfs_create_node (nodeinfo as vfs_create_info ptr)
5 | syscall_param1(SYSCALL_VFS_CREATE_NODE, nodeinfo)
6 | end sub
7 |
8 | 'function frost_syscall_vfs_open (path as zstring ptr, flags as uinteger) as uinteger
9 | ' syscall_param2_ret(SYSCALL_VFS_OPEN, function, path, flags)
10 | 'end function
11 |
12 | sub frost_syscall_vfs_open (openinfo as vfs_open_info ptr)
13 | syscall_param1(SYSCALL_VFS_OPEN, openinfo)
14 | end sub
15 |
--------------------------------------------------------------------------------
/init/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 |
5 | COMPILER = fbc
6 | ASSEMBLER = nasm
7 | LINKER = ld
8 |
9 | CFLAGS = -c -nodeflibs -lang fb -arch 486
10 | AFLAGS = -f elf32
11 | LFLAGS = -melf_i386 -Tinit.ld
12 |
13 | init.elf: $(OBJS)
14 | $(LINKER) $(LFLAGS) -o $@ $^ ../libfrost/libfrost.a
15 |
16 | obj/%.o: src/%.bas
17 | $(COMPILER) $(CFLAGS) $^ -o $@
18 |
19 | obj/%.o: src/%.asm
20 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
21 |
22 | clean:
23 | rm -f $(OBJS) init.elf
24 |
25 | .PHONY: clean
26 |
--------------------------------------------------------------------------------
/drivers/pci/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 |
5 | COMPILER = fbc
6 | ASSEMBLER = nasm
7 | LINKER = ld
8 |
9 | CFLAGS = -c -nodeflibs -lang fb -arch 486
10 | AFLAGS = -f elf32
11 | LFLAGS = -melf_i386 -Tpci.ld
12 |
13 | pci.elf: $(OBJS)
14 | $(LINKER) $(LFLAGS) -o $@ $^ ../../libfrost/libfrost.a
15 |
16 | obj/%.o: src/%.bas
17 | $(COMPILER) $(CFLAGS) $^ -o $@
18 |
19 | obj/%.o: src/%.asm
20 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
21 |
22 | clean:
23 | rm -f $(OBJS) pci.elf
24 |
25 | .PHONY: clean
26 |
--------------------------------------------------------------------------------
/drivers/vgaconsole/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 |
5 | COMPILER = fbc
6 | ASSEMBLER = nasm
7 | LINKER = ld
8 |
9 | CFLAGS = -c -nodeflibs -lang fb -arch 486
10 | AFLAGS = -f elf32
11 | LFLAGS = -melf_i386 -Tvgaconsole.ld
12 |
13 | vgaconsole.elf: $(OBJS)
14 | $(LINKER) $(LFLAGS) -o $@ $^
15 |
16 | obj/%.o: src/%.bas
17 | $(COMPILER) $(CFLAGS) $^ -o $@
18 |
19 | obj/%.o: src/%.asm
20 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
21 |
22 | clean:
23 | rm -f $(OBJS) vgaconsole.elf
24 |
25 | .PHONY: clean
26 |
--------------------------------------------------------------------------------
/drivers/bochsvga/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 |
5 | COMPILER = fbc
6 | ASSEMBLER = nasm
7 | LINKER = ld
8 |
9 | CFLAGS = -c -nodeflibs -lang fb -arch 486
10 | AFLAGS = -f elf32
11 | LFLAGS = -melf_i386 -Tbochsvga.ld
12 |
13 | bochsvga.elf: $(OBJS)
14 | $(LINKER) $(LFLAGS) -o $@ $^ ../../libfrost/libfrost.a
15 |
16 | obj/%.o: src/%.bas
17 | $(COMPILER) $(CFLAGS) $^ -o $@
18 |
19 | obj/%.o: src/%.asm
20 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
21 |
22 | clean:
23 | rm -f $(OBJS) bochsvga.elf
24 |
25 | .PHONY: clean
26 |
--------------------------------------------------------------------------------
/drivers/keyboard/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 |
5 | COMPILER = fbc
6 | ASSEMBLER = nasm
7 | LINKER = ld
8 |
9 | CFLAGS = -c -nodeflibs -lang fb -arch 486
10 | AFLAGS = -f elf32
11 | LFLAGS = -melf_i386 -Tkeyboard.ld
12 |
13 | keyboard.elf: $(OBJS)
14 | $(LINKER) $(LFLAGS) -o $@ $^ ../../libfrost/libfrost.a
15 |
16 | obj/%.o: src/%.bas
17 | $(COMPILER) $(CFLAGS) $^ -o $@
18 |
19 | obj/%.o: src/%.asm
20 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
21 |
22 | clean:
23 | rm -f $(OBJS) keyboard.elf
24 |
25 | .PHONY: clean
26 |
--------------------------------------------------------------------------------
/libfrost/src/thread.bas:
--------------------------------------------------------------------------------
1 | #include "../../kernel/include/syscall_defs.bi"
2 | #include "libfrost_internal.bi"
3 |
4 | function frost_syscall_thread_get_tid () as uinteger
5 | syscall_param0_ret(SYSCALL_THREAD_GET_TID, function)
6 | end function
7 |
8 | function frost_syscall_thread_create (entry as any ptr, stackaddr as any ptr) as integer
9 | syscall_param2_ret(SYSCALL_THREAD_CREATE, function, entry, stackaddr)
10 | end function
11 |
12 | sub frost_syscall_thread_sleep (ms as uinteger)
13 | syscall_param1(SYSCALL_THREAD_SLEEP, ms)
14 | end sub
15 |
16 | sub frost_syscall_thread_yield ()
17 | syscall_param0(SYSCALL_THREAD_YIELD)
18 | end sub
19 |
20 | sub frost_syscall_thread_exit ()
21 | syscall_param0(SYSCALL_THREAD_EXIT)
22 | end sub
23 |
--------------------------------------------------------------------------------
/kernel/kernel.ld:
--------------------------------------------------------------------------------
1 | /* This is the linkerscript for the frost-kernel */
2 | ENTRY(_start)
3 |
4 | SECTIONS
5 | {
6 | /*
7 | * This is where we want to have the kernel loaded
8 | *
9 | */
10 | . = 0x100000;
11 | kernel_start_label = .;
12 |
13 | /*
14 | * The multiboot-header has to be in the first 8 KB,
15 | * so we just put it at the beginning
16 | */
17 | .text : {
18 | *(multiboot)
19 | *(.text)
20 | }
21 | .data ALIGN(4096) : {
22 | start_ctors = .;
23 | *(.ctor*)
24 | end_ctors = .;
25 | start_dtors = .;
26 | *(.dtor*)
27 | end_dtors = .;
28 |
29 | *(.data)
30 | }
31 | .rodata ALIGN(4096) : {
32 | *(.rodata)
33 | }
34 | .bss ALIGN(4096) : {
35 | *(.bss)
36 | }
37 |
38 | .= ALIGN(4096);
39 | kernel_end_label = .;
40 | }
41 |
--------------------------------------------------------------------------------
/kernel/include/pit.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare sub pit_set_frequency (frequency as ushort)
22 |
--------------------------------------------------------------------------------
/kernel/include/idt.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare sub idt_prepare ()
22 | declare sub idt_load ()
23 |
--------------------------------------------------------------------------------
/kernel/include/in_out.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare sub outb (port as ushort, value as ubyte)
22 | declare function inb (port as ushort) as ubyte
23 |
--------------------------------------------------------------------------------
/kernel/include/syscall.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "syscall_defs.bi"
22 |
23 | declare function syscall_handler (param1 as uinteger, param2 as uinteger, param3 as uinteger, param4 as uinteger) as uinteger
24 |
--------------------------------------------------------------------------------
/kernel/include/kmm.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare sub kmm_init (start_addr as uinteger, end_addr as uinteger, minimum as uinteger, maximum as uinteger)
22 | declare function kmalloc (size as uinteger) as any ptr
23 | declare sub kfree (addr as any ptr)
24 |
--------------------------------------------------------------------------------
/kernel/include/modules.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 | #include "multiboot.bi"
21 | #include "process.bi"
22 |
23 | common shared init_process as process_type ptr
24 |
25 | declare sub load_init_module (mbinfo as multiboot_info ptr)
26 | declare sub load_modules (mbinfo as multiboot_info ptr)
27 |
--------------------------------------------------------------------------------
/kernel/Makefile:
--------------------------------------------------------------------------------
1 | SRCS = $(shell find src -name *.bas)
2 | SRCS += $(shell find src -name *.asm)
3 | OBJS = $(addprefix obj/, $(addsuffix .o,$(basename $(notdir $(SRCS)))))
4 | OBJS += obj/trampoline.o
5 |
6 | COMPILER = fbc
7 | ASSEMBLER = nasm
8 | LINKER = ld
9 |
10 | GIT_VERSION := $(shell git describe --dirty --always --tags)
11 |
12 | CFLAGS = -c -nodeflibs -lang fb -arch 486 -i ./include/ -g -d FROST_DEBUG -d FROST_VERSION=\"$(GIT_VERSION)\"
13 | AFLAGS = -f elf32
14 | LFLAGS = -melf_i386 -Tkernel.ld
15 |
16 | frost.krn: $(OBJS)
17 | $(LINKER) $(LFLAGS) -o $@ $^
18 |
19 | obj/%.o: src/%.bas
20 | $(COMPILER) $(CFLAGS) $^ -o $@
21 |
22 | obj/%.o: src/arch/x86/%.bas
23 | $(COMPILER) $(CFLAGS) $^ -o $@
24 |
25 | obj/%.o: src/%.asm
26 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
27 |
28 | obj/%.o: src/arch/x86/%.asm
29 | $(ASSEMBLER) $(AFLAGS) $^ -o $@
30 |
31 | obj/%.bin: src/arch/x86/%.asm.embedd
32 | $(ASSEMBLER) -f bin $^ -o $@
33 |
34 | obj/%.o: obj/%.bin
35 | $(LINKER) -melf_i386 -r -b binary $^ -o $@
36 |
37 | clean:
38 | rm -f $(OBJS) frost.krn
39 |
40 | .PHONY: clean
41 |
--------------------------------------------------------------------------------
/kernel/include/mem.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare sub memcpy (destination as any ptr, source as any ptr, size as uinteger)
22 | declare sub memset (destination as any ptr, value as ubyte, size as uinteger)
23 | declare function memcmp (s1 as any ptr, s2 as any ptr, size as uinteger) as integer
24 |
--------------------------------------------------------------------------------
/kernel/include/elf.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "elf32.bi"
22 | #include "process.bi"
23 |
24 | declare function elf_header_check (header as Elf32_Ehdr ptr) as integer
25 | declare function elf_load_image (process as process_type ptr, thread as thread_type ptr ptr, image as uinteger, size as uinteger) as boolean
26 |
--------------------------------------------------------------------------------
/kernel/include/pic.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 | #include "kernel.bi"
21 |
22 | declare sub pic_init ()
23 | declare sub pic_send_eoi (irq as ubyte)
24 | declare function pic_is_spurious (irq as ubyte) as boolean
25 | declare sub pic_mask (irq as ubyte)
26 | declare sub pic_mask_all ()
27 | declare sub pic_unmask (irq as ubyte)
28 |
--------------------------------------------------------------------------------
/kernel/include/string_tokenizer.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type StringTokenizer
22 | public:
23 | declare constructor (s as zstring ptr)
24 | declare function getToken (delimiters as zstring ptr) as zstring ptr
25 | declare destructor ()
26 |
27 | private:
28 | original_string as ubyte ptr
29 | string_iterator as ubyte ptr
30 | end type
31 |
--------------------------------------------------------------------------------
/kernel/include/spinlock.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include once "kernel.bi"
22 |
23 | type spinlock
24 | public:
25 | declare constructor ()
26 | declare sub acquire ()
27 | declare function trylock () as boolean
28 | declare sub release ()
29 | declare function locked () as boolean
30 |
31 | private:
32 | lockvar as integer
33 | end type
34 |
--------------------------------------------------------------------------------
/kernel/src/pit.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "pit.bi"
20 | #include "in_out.bi"
21 |
22 | const COMMAND_PORT as byte = &h43
23 | const DATA_PORT as byte = &h40
24 |
25 | sub pit_set_frequency (frequency as ushort)
26 | frequency = 1193182 \ frequency
27 | outb(COMMAND_PORT, &h34)
28 | outb(DATA_PORT, lobyte(frequency))
29 | outb(DATA_PORT, hibyte(frequency))
30 | end sub
31 |
--------------------------------------------------------------------------------
/kernel/include/interrupt.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | extern interrupt_legacy_free as boolean
22 |
23 | declare sub interrupt_init ()
24 | declare sub interrupt_mask (interrupt as integer)
25 | declare sub interrupt_unmask (interrupt as integer)
26 | declare function interrupt_is_spurious (interrupt as integer) as boolean
27 | declare sub interrupt_eoi (interrupt as integer)
28 |
--------------------------------------------------------------------------------
/kernel/include/zstring.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2014 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | declare function zstring_len (zstr as zstring) as uinteger
22 | declare function zstring_instr (zstr as zstring, substr as zstring) as uinteger
23 | declare function zstring_cmp (zstr1 as zstring, zstr2 as zstring) as integer
24 | declare function zstring_ncmp (zstr1 as zstring, zstr2 as zstring, n as uinteger) as integer
25 |
--------------------------------------------------------------------------------
/kernel/include/interrupt_handler.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "isf.bi"
22 | #include "process.bi"
23 | #include "kernel.bi"
24 |
25 | declare function register_irq_handler (process as process_type ptr, irq as integer, handler_address as any ptr) as boolean
26 |
27 | '' the global interrupt-handler
28 | declare function handle_interrupt cdecl (isf as interrupt_stack_frame ptr) as interrupt_stack_frame ptr
29 |
--------------------------------------------------------------------------------
/kernel/src/arch/x64/atomic_arch.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "atomic.bi"
20 |
21 | function AtomicInt.cmpxchg (oldval as integer, newval as integer) as integer
22 | dim result as integer
23 |
24 | asm
25 | mov rax, [oldval]
26 | mov rbx, [newval]
27 | mov rdx, [this+offsetof(AtomicInt, counter)]
28 |
29 | lock cmpxchg qword ptr [rdx], rbx
30 | mov [result], rax
31 | end asm
32 |
33 | return result
34 | end function
35 |
--------------------------------------------------------------------------------
/kernel/src/arch/x86/atomic_arch.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "atomic.bi"
20 |
21 | function AtomicInt.cmpxchg (oldval as integer, newval as integer) as integer
22 | dim result as integer
23 |
24 | asm
25 | mov eax, [oldval]
26 | mov ebx, [newval]
27 | mov edx, [this+offsetof(AtomicInt, counter)]
28 |
29 | lock cmpxchg dword ptr [edx], ebx
30 | mov [result], eax
31 | end asm
32 |
33 | return result
34 | end function
35 |
--------------------------------------------------------------------------------
/kernel/src/in_out.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | '' this code is a bit strange, but it's the only comfortable way to use in/out in FreeBASIC without the rtlib (which can't be used in a kernel)
20 |
21 | sub outb (port as ushort, value as ubyte)
22 | asm
23 | movw dx, [port]
24 | movb al, [value]
25 | outb dx, al
26 | end asm
27 | end sub
28 |
29 | function inb (port as ushort) as ubyte
30 | asm
31 | movw dx, [port]
32 | inb al, dx
33 | mov [function], al
34 | end asm
35 | end function
36 |
--------------------------------------------------------------------------------
/kernel/include/kernel.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | extern kernel_start_label alias "kernel_start_label" as byte
22 | extern kernel_end_label alias "kernel_end_label" as byte
23 |
24 | #define kernel_start @kernel_start_label
25 | #define kernel_end @kernel_end_label
26 |
27 | #include "gdt.bi"
28 | common shared tss_ptr as task_state_segment ptr
29 |
30 | const nullptr as any ptr = cast(any ptr, 0)
31 |
32 | type paddr_t as uinteger
33 | type vaddr_t as uinteger
34 | type addr_t as uinteger
35 | #define caddr(cf) cuint(cf)
36 |
--------------------------------------------------------------------------------
/kernel/include/io_man.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "process.bi"
22 |
23 | declare sub init_ports ()
24 | declare function request_port (process as process_type ptr, port as uinteger) as boolean
25 | declare function release_port (process as process_type ptr, port as uinteger) as boolean
26 | declare function request_port_range (process as process_type ptr, start_port as uinteger, length as uinteger) as boolean
27 | declare function release_port_range (process as process_type ptr, start_port as uinteger, length as uinteger) as boolean
28 |
--------------------------------------------------------------------------------
/kernel/include/syscall_defs.bi:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum syscalls
4 | SYSCALL_KERNEL_REQUEST_FAST_SYSCALL_INTERFACE
5 |
6 | SYSCALL_PROCESS_GET_PID
7 | SYSCALL_PROCESS_GET_PARENT_PID
8 | SYSCALL_PROCESS_CREATE
9 | SYSCALL_PROCESS_EXIT
10 | SYSCALL_PROCESS_KILL
11 |
12 | SYSCALL_THREAD_GET_TID
13 | SYSCALL_THREAD_CREATE
14 | SYSCALL_THREAD_SLEEP
15 | SYSCALL_THREAD_YIELD
16 | SYSCALL_THREAD_EXIT
17 |
18 | SYSCALL_MEMORY_ALLOCATE_PHYSICAL
19 |
20 | SYSCALL_PORT_REQUEST
21 | SYSCALL_PORT_RELEASE
22 |
23 | SYSCALL_IRQ_HANDLER_REGISTER
24 | SYSCALL_IRQ_HANDLER_EXIT
25 |
26 | SYSCALL_IPC_HANDLER_CALL
27 | SYSCALL_IPC_HANDLER_SET
28 | SYSCALL_IPC_HANDLER_EXIT
29 |
30 | SYSCALL_VFS_CREATE_NODE
31 | SYSCALL_VFS_OPEN
32 | SYSCALL_VFS_CLOSE
33 | SYSCALL_VFS_READ
34 | SYSCALL_VFS_WRITE
35 |
36 | SYSCALL_FORTY_TWO = 42
37 | end enum
38 |
39 | type vfs_create_info
40 | pathname as zstring ptr
41 | nodename as zstring ptr
42 | handler as any ptr
43 | id as integer
44 | end type
45 |
46 | type vfs_open_info
47 | path as zstring ptr '*< the complete path of the node which is to be opened
48 | flags as uinteger
49 | handle as uinteger '*< a caller-defined handle which gets passed to the callback
50 | callback as any ptr '*< the address of a function that gets called as a callback
51 | end type
52 |
--------------------------------------------------------------------------------
/kernel/include/debug.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "video.bi"
22 |
23 | const DEBUG_INFO as ubyte = 1
24 | const DEBUG_ERROR as ubyte = 3
25 |
26 | common shared debug_loglevel as ubyte
27 |
28 | declare sub debug_set_loglevel (level as ubyte)
29 |
30 | #macro debug_wlog(level, fstr, args...)
31 | if (level>debug_loglevel) then video_fout(fstr, args)
32 | #endmacro
33 |
34 | #if defined (FROST_DEBUG)
35 | declare sub debug_serial_init ()
36 | declare sub debug_serial_putc (char as ubyte)
37 | #endif
38 |
39 | declare sub debug_stacktrace (maxFrames as uinteger)
40 |
--------------------------------------------------------------------------------
/kernel/include/cpu.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 | #include "kernel.bi"
21 |
22 | declare sub cpu_get_vendor (zstr as zstring ptr)
23 | declare function cpu_has_local_apic () as boolean
24 | declare function cpu_supports_PGE () as boolean
25 | declare function read_msr (msr as uinteger) as ulongint
26 | declare sub write_msr (msr as uinteger, value as ulongint)
27 | declare sub cpu_halt ()
28 | declare sub cpu_disable_interrupts ()
29 |
30 | const MSR_IA32_SYSENTER_CS as uinteger = &h0174
31 | const MSR_IA32_SYSENTER_ESP as uinteger = &h0175
32 | const MSR_IA32_SYSENTER_EIP as uinteger = &h0176
33 |
--------------------------------------------------------------------------------
/kernel/include/apic.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 |
23 | extern apic_enabled as boolean
24 |
25 | declare sub set_interrupt_override (irq as uinteger, gsi as uinteger, active_high as boolean, edge_triggered as boolean)
26 | declare sub lapic_init ()
27 | declare sub lapic_eoi ()
28 | declare sub ioapic_init ()
29 | declare sub lapic_startup_ipi (trampoline_addr as any ptr)
30 | declare sub ioapic_unmask_irq (irq as uinteger)
31 | declare sub ioapic_mask_irq (irq as uinteger)
32 | declare sub ioapic_register (base_p as uinteger, global_system_interrupt_base as uinteger)
33 |
--------------------------------------------------------------------------------
/kernel/include/isf.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type interrupt_stack_frame field=1
22 | exit_with_iret as uinteger
23 |
24 | '' saved per asm-code:
25 | eax as uinteger
26 | ebx as uinteger
27 | ecx as uinteger
28 | edx as uinteger
29 | esi as uinteger
30 | edi as uinteger
31 | ebp as uinteger
32 |
33 | '' saved by asm-code to identify the interrupt
34 | int_nr as uinteger
35 | errorcode as uinteger
36 |
37 | '' saved automatically by the cpu:
38 | eip as uinteger
39 | cs as uinteger
40 | eflags as uinteger
41 | esp as uinteger
42 | ss as uinteger
43 | end type
44 |
--------------------------------------------------------------------------------
/libfrost/src/libfrost_internal.bi:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #macro syscall_param0(syscall_nr)
4 | asm
5 | mov eax, syscall_nr
6 | int &hFF
7 | end asm
8 | #endmacro
9 |
10 | #macro syscall_param1(syscall_nr, a)
11 | asm
12 | mov eax, syscall_nr
13 | mov ebx, [a]
14 | int &hFF
15 | end asm
16 | #endmacro
17 |
18 | #macro syscall_param2(syscall_nr, a, b)
19 | asm
20 | mov eax, syscall_nr
21 | mov ebx, [a]
22 | mov esi, [b]
23 | int &hFF
24 | end asm
25 | #endmacro
26 |
27 | #macro syscall_param3(syscall_nr, a, b, c)
28 | asm
29 | mov eax, syscall_nr
30 | mov ebx, [a]
31 | mov esi, [b]
32 | mov edi, [c]
33 | int &hFF
34 | end asm
35 | #endmacro
36 |
37 | #macro syscall_param0_ret(syscall_nr, ret)
38 | asm
39 | mov eax, syscall_nr
40 | int &hFF
41 | mov [ret], eax
42 | end asm
43 | #endmacro
44 |
45 | #macro syscall_param1_ret(syscall_nr, ret, a)
46 | asm
47 | mov eax, syscall_nr
48 | mov ebx, [a]
49 | int &hFF
50 | mov [ret], eax
51 | end asm
52 | #endmacro
53 |
54 | #macro syscall_param2_ret(syscall_nr, ret, a, b)
55 | asm
56 | mov eax, syscall_nr
57 | mov ebx, [a]
58 | mov esi, [b]
59 | int &hFF
60 | mov [ret], eax
61 | end asm
62 | #endmacro
63 |
64 | #macro syscall_param3_ret(syscall_nr, ret, a, b, c)
65 | asm
66 | mov eax, syscall_nr
67 | mov ebx, [a]
68 | mov esi, [b]
69 | mov edi, [c]
70 | int &hFF
71 | mov [ret], eax
72 | end asm
73 | #endmacro
74 |
--------------------------------------------------------------------------------
/kernel/include/atomic.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 |
22 | type AtomicInt
23 | public:
24 | declare sub inc ()
25 | declare sub dec ()
26 | declare function get () as integer
27 | declare function cmpxchg (oldval as integer, newval as integer) as integer
28 | declare function add (value as integer) as integer
29 | declare function subtract (value as integer) as integer
30 | declare function sub_and_test (value as integer) as boolean
31 |
32 | declare constructor ()
33 | declare constructor (i as integer)
34 | private:
35 | counter as integer
36 | end type
37 |
--------------------------------------------------------------------------------
/libfrost/frost.bi:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../kernel/include/syscall_defs.bi"
4 |
5 | declare function frost_syscall_process_get_pid () as uinteger
6 | declare function frost_syscall_get_parent_pid () as uinteger
7 |
8 | declare function frost_syscall_thread_get_tid () as uinteger
9 | declare function frost_syscall_thread_create (entry as any ptr, stackaddr as any ptr) as integer
10 | declare sub frost_syscall_thread_sleep (ms as uinteger)
11 | declare sub frost_syscall_thread_yield ()
12 | declare sub frost_syscall_thread_exit ()
13 |
14 | declare function frost_syscall_memory_allocate_physical (bytes as uinteger, addr as any ptr) as any ptr
15 |
16 | declare sub frost_syscall_port_request (port as uinteger)
17 | declare sub frost_syscall_port_release (port as uinteger)
18 |
19 | declare sub frost_syscall_irq_handler_register (irq as uinteger, function_pointer as any ptr)
20 | declare sub frost_syscall_irq_handler_exit (irq as uinteger)
21 |
22 | declare sub frost_syscall_ipc_handler_call (pid as uinteger)
23 | declare sub frost_syscall_ipc_handler_set (handler as any ptr)
24 | declare sub frost_syscall_ipc_handler_exit ()
25 |
26 | declare sub frost_syscall_vfs_create_node (nodeinfo as vfs_create_info ptr)
27 | 'declare function frost_syscall_vfs_open (path as zstring ptr, flags as uinteger) as uinteger
28 | declare sub frost_syscall_vfs_open (openinfo as vfs_open_info ptr)
29 |
30 | declare sub frost_syscall_43 (str_ptr as byte ptr)
31 |
--------------------------------------------------------------------------------
/kernel/include/uid128.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "spinlock.bi"
22 |
23 | type uid128
24 | #ifdef __FB_BIGENDIAN__
25 | h as uinteger<64>
26 | l as uinteger<64>
27 | #else
28 | l as uinteger<64>
29 | h as uinteger<64>
30 | #endif
31 |
32 | declare constructor (h as uinteger<64>, l as uinteger<64>)
33 | declare constructor (id as uid128)
34 | declare constructor ()
35 | declare sub inc ()
36 | end type
37 |
38 | type uid128_generator
39 | current_id as uid128
40 | id_lock as spinlock
41 |
42 | declare constructor ()
43 | declare constructor (id as uid128)
44 | declare function generate () as uid128
45 | end type
46 |
--------------------------------------------------------------------------------
/kernel/src/assert.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "video.bi"
20 | #include "debug.bi"
21 | #include "cpu.bi"
22 |
23 | #if defined (FROST_DEBUG)
24 | sub _fb_Assert alias "fb_Assert" (byval fname as zstring ptr, byval linenum as integer, byval funcname as zstring ptr, byval expression as zstring ptr)
25 | printk(LOG_ERR !"%s(%i): assertion failed at %s: %s\n", fname, linenum, funcname, expression)
26 | debug_stacktrace(10)
27 | cpu_halt()
28 | end sub
29 |
30 | sub _fb_AssertWarn alias "fb_AssertWarn" (byval fname as zstring ptr, byval linenum as integer, byval funcname as zstring ptr, byval expression as zstring ptr)
31 | printk(LOG_ERR !"%s(%i): assertion failed at %s: %s\n", fname, linenum, funcname, expression)
32 | end sub
33 | #endif
34 |
--------------------------------------------------------------------------------
/drivers/vgaconsole/src/main.bas:
--------------------------------------------------------------------------------
1 | #include "../../../kernel/include/syscall_defs.bi"
2 |
3 | declare sub _fb_Out cdecl alias "fb_Out" (port as ushort, value as ubyte)
4 | declare function _fb_In cdecl alias "fb_In" (port as ushort) as ubyte
5 |
6 | asm
7 | .global fb_ctor__main
8 | end asm
9 |
10 | '' request access to the textbuffer
11 | dim buffer as byte ptr
12 |
13 | asm
14 | mov eax, syscalls.SYSCALL_MEMORY_ALLOCATE_PHYSICAL
15 | mov ebx, 4096
16 | mov ecx, &hb8000
17 | int &hFF
18 | mov [buffer], eax
19 | end asm
20 |
21 | asm
22 | mov eax, syscalls.SYSCALL_PORT_REQUEST
23 | mov ebx, &h3D4
24 | int &hFF
25 | mov eax, syscalls.SYSCALL_PORT_REQUEST
26 | mov ebx, &h3D5
27 | int &hFF
28 | end asm
29 |
30 | out(&h3D4, 14)
31 | out(&h3D5, &h07)
32 | out(&h3D4, 15)
33 | out(&h3D5, &hD0)
34 |
35 | 'for x as uinteger = 0 to 4000
36 | ' buffer[x] = 0
37 | 'next
38 |
39 | dim r as uinteger = 0
40 |
41 | dim x as byte ptr = strptr("this is a test from the vgaconsole-driver!")
42 | dim c as uinteger = 0
43 | while (x[c] <> 0)
44 | buffer[r] = x[c]
45 | c += 1
46 | r += 1
47 | buffer[r] = 7
48 | r += 1
49 | wend
50 |
51 |
52 | asm jmp $
53 |
54 |
55 | sub _fb_Out cdecl alias "fb_Out" (port as ushort, value as ubyte)
56 | asm
57 | movw dx, [port]
58 | movb al, [value]
59 | outb dx, al
60 | end asm
61 | end sub
62 |
63 | function _fb_In cdecl alias "fb_In" (port as ushort) as ubyte
64 | asm
65 | movw dx, [port]
66 | inb al, dx
67 | mov [function], al
68 | end asm
69 | end function
70 |
--------------------------------------------------------------------------------
/kernel/include/acpi.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type rsdp_descriptor field=1
22 | signature as zstring*8
23 | checksum as ubyte
24 | oemid as zstring*6
25 | revision as ubyte
26 | rsdt_address as uinteger<32>
27 | end type
28 |
29 | type rsdp_descriptor_20 field=1
30 | firstPart as rsdp_descriptor
31 |
32 | length as uinteger<32>
33 | xsdt_address as uinteger<64>
34 | extended_checksum as ubyte
35 | reserved as zstring*3
36 | end type
37 |
38 | type sdt_header field=1
39 | signature as zstring*4
40 | length as uinteger<32>
41 | revision as ubyte
42 | checksum as ubyte
43 | oemid as zstring*6
44 | oemtableid as zstring*8
45 | oemrevision as uinteger<32>
46 | creatorid as uinteger<32>
47 | creatorrevision as uinteger<32>
48 | end type
49 |
50 | declare sub acpi_init ()
51 |
--------------------------------------------------------------------------------
/kernel/include/panic.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 | #include "isf.bi"
23 | #include "video.bi"
24 | #include "cpu.bi"
25 |
26 | common shared panic_clear_on_panic as boolean
27 | declare sub panic_set_clear_on_panic (b as boolean)
28 | declare sub panic_exception (isf as interrupt_stack_frame ptr)
29 | declare sub panic_hlt ()
30 |
31 | #macro panic_error (msg, params...)
32 | cpu_disable_interrupts()
33 | if (panic_clear_on_panic) then video_clean()
34 | printk(LOG_ERR COLOR_RED !"\n--------------------------------------------------------------------------------")
35 | printk(LOG_ERR !"\nKERNEL PANIC\n")
36 | printk(LOG_ERR !"file: %s, function: %s, line: %u\n\n", @__FILE__, @__FUNCTION__, cuint(__LINE__))
37 | printk(LOG_ERR !"reason: ")
38 | printk(LOG_ERR msg, params)
39 |
40 | panic_hlt()
41 | #endmacro
42 |
--------------------------------------------------------------------------------
/kernel/include/video.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #define LOG_DEBUG !"\0022"
22 | #define LOG_INFO !"\0021"
23 | #define LOG_ERR !"\0020"
24 |
25 | #define LOGLEVEL_DEBUG 2
26 | #define LOGLEVEL_INFO 1
27 | #define LOGLEVEL_ERR 0
28 |
29 | #define COLOR_BLACK !"\27[30m"
30 | #define COLOR_RED !"\27[31m"
31 | #define COLOR_GREEN !"\27[32m"
32 | #define COLOR_YELLOW !"\27[33m"
33 | #define COLOR_BLUE !"\27[34m"
34 | #define COLOR_MAGENTA !"\27[35m"
35 | #define COLOR_CYAN !"\27[36m"
36 | #define COLOR_WHITE !"\27[37m"
37 | #define COLOR_RESET !"\27[0m"
38 |
39 | declare sub video_serial_set_colorized (b as integer)
40 | declare sub printk (format_string as const zstring, ...)
41 | declare sub video_clean ()
42 | declare sub video_hide_cursor ()
43 | declare sub video_show_cursor ()
44 | declare sub video_move_cursor (x as ubyte, y as ubyte)
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | FROST
2 | ======
3 |
4 | #### What is FROST? ####
5 | FROST is a 32-bit operating system based on a microkernel. It is written
6 | entirely in FreeBASIC and Assembly.
7 |
8 | #### Dependencies ####
9 | - fbc, tested with 1.05.0 (the FreeBASIC compiler, available on freebasic.net)
10 | - nasm, tested with 2.11.08 (the Netwide Assembler, available on nasm.us)
11 | - GNU make, GNU assembler and the GNU linker
12 |
13 | #### Building FROST ####
14 | To build the kernel, you can type "make" in the "kernel" directory. You will then
15 | get a file called "frost.krn" which is the kernel.
16 | Building the init-process is very similar.
17 | If you want to get a full iso with grub2 and a menu, type "./build_iso.sh" in
18 | the "build"-directory. You will then get a file called "frost.iso" which is
19 | the iso-image.
20 | On some Linux distributions the script will fail because they contain
21 | genisoimage from cdrkit instead of mkisofs from cdrtools. You can create
22 | a link on genisoimage named mkisofs, but I strongly recommend installing
23 | cdrtools instead of cdrkit. If cdrtools is not available on your distribution,
24 | please contact its maintainers (I don't want to get into a debate here, but
25 | cdrkit received it's last commit three years ago).
26 |
27 | #### Directory layout ####
28 |
29 | - ./kernel/src/ The source of the kernel
30 | - ./kernel/include/ The headers of the kernel
31 | - ./build/ Contains the build-scripts and the grub.cfg
32 | - ./doc/ Contains documentation for FROST
33 | - ./init/ Contains the source of the init-process
34 |
--------------------------------------------------------------------------------
/kernel/include/pmm.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 | #include "multiboot.bi"
23 |
24 | const PAGE_SIZE = 4096
25 | const PMM_STACK_TOP = &h3FC00000
26 | const PMM_STACK_ENTRIES_PER_PAGE = 1024
27 |
28 | const PMM_ZONE_DMA24 as uinteger = 1
29 | const PMM_ZONE_NORMAL as uinteger = 2
30 |
31 | declare sub pmm_init (mbinfo as multiboot_info ptr, zone as uinteger)
32 | declare function pmm_alloc (zone as uinteger = PMM_ZONE_NORMAL) as any ptr
33 | declare sub pmm_free (page as any ptr)
34 | declare function pmm_get_total () as uinteger
35 | declare function pmm_get_free () as uinteger
36 |
37 | declare sub pmm_init_dma24 ()
38 | declare function pmm_alloc_dma24 () as any ptr
39 | declare sub pmm_free_dma24 (page as any ptr)
40 | declare function pmm_alloc_normal () as any ptr
41 | declare sub pmm_free_normal (addr as any ptr)
42 |
--------------------------------------------------------------------------------
/kernel/src/mem.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "mem.bi"
20 |
21 | sub memcpy (destination as any ptr, source as any ptr, size as uinteger)
22 | asm
23 | mov ecx, [size]
24 | mov edi, [destination]
25 | mov esi, [source]
26 |
27 | rep movsb
28 | end asm
29 | end sub
30 |
31 | sub memset (destination as any ptr, value as ubyte, size as uinteger)
32 | asm
33 | mov ecx, [size]
34 | mov edi, [destination]
35 | mov al, [value]
36 |
37 | rep stosb
38 | end asm
39 | end sub
40 |
41 | function memcmp (s1 as any ptr, s2 as any ptr, size as uinteger) as integer
42 | dim p1 as ubyte ptr = s1
43 | dim p2 as ubyte ptr = s2
44 |
45 | while (size > 0)
46 | if (*p1 <> *p2) then
47 | return *p1 - *p2
48 | end if
49 |
50 | p1 += 1
51 | p2 += 1
52 | size -= 1
53 | wend
54 |
55 | return 0
56 | end function
57 |
--------------------------------------------------------------------------------
/kernel/include/address_space.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 | #include "intrusive_list.bi"
23 |
24 | DECLARE_LIST(address_space_area)
25 |
26 | type address_space_area
27 | address as any ptr
28 | pages as uinteger
29 | flags as uinteger
30 | description as zstring ptr
31 |
32 | list as Listtype(address_space_area) = Listtype(address_space_area)(offsetof(address_space_area, list))
33 |
34 | declare constructor (address as any ptr, pages as uinteger, flags as uinteger = 0, description as zstring ptr = nullptr)
35 | declare operator new (size as uinteger) as any ptr
36 | declare operator delete (buffer as any ptr)
37 | end type
38 |
39 | type address_space
40 | areas as Listtype(address_space_area)
41 |
42 | declare function allocate_area (pages as uinteger, flags as uinteger = 0, description as zstring ptr = nullptr) as address_space_area ptr
43 | declare sub insert_area (area as address_space_area ptr)
44 | end type
45 |
--------------------------------------------------------------------------------
/kernel/src/atomic.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "atomic.bi"
20 |
21 | sub AtomicInt.inc ()
22 | this.add(1)
23 | end sub
24 |
25 | sub AtomicInt.dec ()
26 | this.add(-1)
27 | end sub
28 |
29 | function AtomicInt.get () as integer
30 | return this.counter
31 | end function
32 |
33 | function AtomicInt.add (value as integer) as integer
34 | dim c as integer = this.counter
35 | dim old as integer
36 |
37 | do
38 | old = this.cmpxchg(c, c+value)
39 | if (old = c) then exit do
40 | c = old
41 | loop
42 |
43 | return c+value
44 | end function
45 |
46 | function AtomicInt.subtract (value as integer) as integer
47 | return this.add(-value)
48 | end function
49 |
50 | function AtomicInt.sub_and_test (value as integer) as boolean
51 | return this.subtract(value) = 0
52 | end function
53 |
54 | constructor AtomicInt ()
55 | this.counter = 0
56 | end constructor
57 |
58 | constructor AtomicInt (i as integer)
59 | this.counter = i
60 | end constructor
61 |
--------------------------------------------------------------------------------
/kernel/src/uid128.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "uid128.bi"
20 |
21 | constructor uid128 (h as uinteger<64>, l as uinteger<64>)
22 | this.h = h
23 | this.l = l
24 | end constructor
25 |
26 | constructor uid128 (id as uid128)
27 | this.h = id.h
28 | this.l = id.l
29 | end constructor
30 |
31 | constructor uid128 ()
32 | this.l = 0
33 | this.h = 0
34 | end constructor
35 |
36 | sub uid128.inc ()
37 | dim r as uid128
38 | r.l = this.l+1
39 | r.h = this.h + iif(r.l < this.l, 1, 0)
40 |
41 | this.l = r.l
42 | this.h = r.h
43 | end sub
44 |
45 | constructor uid128_generator ()
46 |
47 | end constructor
48 |
49 | constructor uid128_generator (id as uid128)
50 | this.id_lock.acquire()
51 | this.current_id = id
52 | this.id_lock.release()
53 | end constructor
54 |
55 | function uid128_generator.generate () as uid128
56 | this.id_lock.acquire()
57 | function = this.current_id
58 | this.current_id.inc()
59 | this.id_lock.release()
60 | end function
61 |
--------------------------------------------------------------------------------
/kernel/include/gdt.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type task_state_segment field=1
22 | backlink as uinteger
23 | esp0 as uinteger
24 | ss0 as uinteger
25 | esp1 as uinteger
26 | ss1 as uinteger
27 | esp2 as uinteger
28 | ss2 as uinteger
29 | cr3 as uinteger
30 | eip as uinteger
31 | eflags as uinteger
32 | eax as uinteger
33 | ecx as uinteger
34 | edx as uinteger
35 | ebx as uinteger
36 | esp as uinteger
37 | ebp as uinteger
38 | esi as uinteger
39 | edi as uinteger
40 | es as uinteger
41 | cs as uinteger
42 | ss as uinteger
43 | ds as uinteger
44 | fs as uinteger
45 | gs as uinteger
46 | ldt as uinteger
47 | trace_trap as ushort
48 | io_bitmap_offset as ushort
49 | io_bitmap(0 to 2047) as uinteger
50 | io_bitmap_end as ubyte
51 | end type
52 |
53 | const TSS_IO_BITMAP_OFFSET as ushort = cushort(cuint(@(cast(task_state_segment ptr, 0)->io_bitmap(0))))
54 | const TSS_IO_BITMAP_NOT_LOADED as ushort = sizeof(task_state_segment)+&h100
55 |
56 | declare sub gdt_prepare ()
57 | declare sub gdt_load ()
58 |
--------------------------------------------------------------------------------
/kernel/src/spinlock.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "spinlock.bi"
20 | #include "kernel.bi"
21 |
22 | constructor spinlock ()
23 | this.lockvar = 0
24 | end constructor
25 |
26 | sub spinlock.acquire ()
27 | dim slock as integer ptr = @this.lockvar
28 | asm
29 | mov ecx, [slock]
30 | .acquire:
31 | lock bts dword ptr [ecx], 0
32 | jnc .acquired
33 | .retest:
34 | pause
35 | test dword ptr [ecx], 1
36 | je .retest
37 |
38 | lock bts dword ptr [ecx], 0
39 | jc .retest
40 | .acquired:
41 | end asm
42 | end sub
43 |
44 | function spinlock.trylock () as boolean
45 | dim slock as integer ptr = @this.lockvar
46 | asm
47 | mov ecx, [slock]
48 | lock bts dword ptr [ecx], 0
49 | jc .not_locked
50 | mov dword ptr [function], true
51 | jmp .fend
52 | .not_locked:
53 | mov dword ptr [function], false
54 | .fend:
55 | end asm
56 | end function
57 |
58 | sub spinlock.release ()
59 | this.lockvar = 0
60 | end sub
61 |
62 | function spinlock.locked () as boolean
63 | return (this.lockvar <> 0)
64 | end function
65 |
--------------------------------------------------------------------------------
/init/src/init.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "../libfrost/frost.bi"
20 | 'asm
21 | ' .global fb_ctor__init
22 | 'end asm
23 |
24 | sub vfs_handler (node_id as uinteger)
25 | frost_syscall_43(strptr("vfs handler called"))
26 | '' FIXME
27 | frost_syscall_thread_exit()
28 | 'do : loop
29 | end sub
30 |
31 | sub open_callback ()
32 | frost_syscall_43(strptr("open-callback called"))
33 | '' FIXME
34 | frost_syscall_thread_exit()
35 | 'do : loop
36 | end sub
37 |
38 | sub main ()
39 | frost_syscall_43(strptr("this is a test"))
40 |
41 | dim ninfo as vfs_create_info
42 | ninfo.pathname = strptr("/vfs_2/testnode")
43 | ninfo.nodename = strptr("INIT_WAS_HERE")
44 | ninfo.handler = @vfs_handler
45 | ninfo.id = 0
46 | frost_syscall_vfs_create_node(@ninfo)
47 |
48 | dim openinfo as vfs_open_info
49 | openinfo.path = strptr("/vfs_2/testnode/INIT_WAS_HERE")
50 | openinfo.flags = &hDEADC0DE
51 | openinfo.handle = &hDEADBEEF
52 | openinfo.callback = @open_callback
53 | frost_syscall_vfs_open(@openinfo)
54 |
55 | do
56 | frost_syscall_thread_yield()
57 | loop
58 | end sub
59 |
--------------------------------------------------------------------------------
/kernel/include/process.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "isf.bi"
22 | #include "vmm.bi"
23 | #include "elf32.bi"
24 | #include "multiboot.bi"
25 | #include "thread.bi"
26 | #include "spinlock.bi"
27 | #include "address_space.bi"
28 | #include "vfs.bi"
29 |
30 | DECLARE_LIST(process_type)
31 |
32 | type process_type
33 | id as uinteger
34 |
35 | parent as process_type ptr
36 |
37 | context as vmm_context
38 |
39 | a_s as address_space
40 |
41 | state as ubyte
42 |
43 | ipc_handler as any ptr
44 |
45 | io_bitmap as uinteger ptr
46 |
47 | thread_list as Listtype(thread_type)
48 | next_tid as uinteger
49 | tid_lock as spinlock
50 |
51 | process_list as Listtype(process_type) = Listtype(process_type)(offsetof(process_type, process_list))
52 |
53 | file_descriptors as Listtype(vfs_fd)
54 |
55 | declare operator new (size as uinteger) as any ptr
56 | declare operator new[] (size as uinteger) as any ptr
57 | declare operator delete (buffer as any ptr)
58 |
59 | declare constructor (parent as process_type ptr = 0)
60 | declare function get_tid () as uinteger
61 | end type
62 |
63 | declare sub process_remove_thread (thread as thread_type ptr)
64 | declare sub process_destroy (process as process_type ptr)
65 |
--------------------------------------------------------------------------------
/kernel/src/arch/arm/start.S:
--------------------------------------------------------------------------------
1 | // FROST x86 microkernel
2 | // Copyright (C) 2010-2016 Stefan Schmidt
3 | //
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 |
17 | .extern MAIN
18 | .extern KINIT
19 |
20 | .globl _start
21 |
22 | // First we define some constants here,
23 | // then the multiboot header follows.
24 | // Notice that the mb-header has it's own section
25 | // which is mapped to the beginning of .text by
26 | // the linkerscript to prevent it from falling behind
27 | // the first 8KB of the kernel (which would mean problems with grub).
28 |
29 | .section multiboot
30 | .align 4
31 |
32 | .set MULTIBOOT_HEADER_MAGIC, 0x1BADB002
33 | .set MULTIBOOT_PAGE_ALIGN, 0x00000001
34 | .set MULTIBOOT_MEMORY_INFO, 0x00000002
35 | .set MB_FLAGS, MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
36 | .set MB_CHECKSUM, -(MULTIBOOT_HEADER_MAGIC+MB_FLAGS)
37 |
38 | .long MULTIBOOT_HEADER_MAGIC
39 | .long MB_FLAGS
40 | .long MB_CHECKSUM
41 |
42 | // This is the entry-point of the kernel.
43 | .section .text
44 | _start:
45 | ldr sp, =kernelstack // set up the stack
46 | blx KINIT
47 | blx MAIN // multiboot pointer and magic number are passed in registers
48 |
49 | _halt:
50 | wfe
51 | b _halt
52 |
53 | // 4KB stack for the kernel should be enough ;)
54 | // The label comes after the 4KB because the stack grows downwards.
55 | .section .bss
56 | .space 4096
57 | kernelstack:
58 |
--------------------------------------------------------------------------------
/kernel/src/arch/x86/start.asm:
--------------------------------------------------------------------------------
1 | ; FROST x86 microkernel
2 | ; Copyright (C) 2010-2014 Stefan Schmidt
3 | ;
4 | ; This program is free software: you can redistribute it and/or modify
5 | ; it under the terms of the GNU General Public License as published by
6 | ; the Free Software Foundation, either version 3 of the License, or
7 | ; (at your option) any later version.
8 | ;
9 | ; This program is distributed in the hope that it will be useful,
10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | ; GNU General Public License for more details.
13 | ;
14 | ; You should have received a copy of the GNU General Public License
15 | ; along with this program. If not, see .
16 | extern MAIN
17 | extern KINIT
18 | global _start
19 |
20 |
21 | ; First we define some constants here,
22 | ; then the multiboot header follows.
23 | ; Notice that the mb-header has it's own section
24 | ; which is mapped to the beginning of .text by
25 | ; the linkerscript to prevent it from falling behind
26 | ; the first 8KB of the kernel (which would mean problems with grub).
27 | section multiboot
28 | align 4
29 |
30 | MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
31 | MULTIBOOT_PAGE_ALIGN equ 0x00000001
32 | MULTIBOOT_MEMORY_INFO equ 0x00000002
33 | MB_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
34 | MB_CHECKSUM equ -MULTIBOOT_HEADER_MAGIC-MB_FLAGS
35 |
36 | dd MULTIBOOT_HEADER_MAGIC
37 | dd MB_FLAGS
38 | dd MB_CHECKSUM
39 |
40 |
41 | ; This is the entry-point of the kernel.
42 | section .text
43 | _start:
44 | cli ;; no interrupts during initialization
45 | mov esp, kernelstack ;; set up the stack
46 | push ebx ;; pointer to the multiboot structure
47 | push eax ;; push the multiboot magic number
48 | call KINIT
49 | call MAIN
50 |
51 | cli
52 | hlt
53 |
54 | ; 4KB stack for the kernel should be enough ;)
55 | ; The label comes after the 4KB because the stack grows downwards.
56 | section .bss
57 | resb 4096
58 | kernelstack:
59 |
--------------------------------------------------------------------------------
/drivers/keyboard/src/sc2kc.bas:
--------------------------------------------------------------------------------
1 | dim shared scancode_table (0 to 127) as ubyte = { _
2 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, _
3 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, _
4 | 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, _
5 | 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, _
6 | 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, _
7 | 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, _
8 | 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, _
9 | 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, _
10 | 80, 81, 82, 84, 00, 00, 86, 87, 88, 00, _
11 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
12 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
13 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
14 | 00, 00, 00, 00, 00, 00, 00, 00 }
15 |
16 | dim shared e0code_table (0 to 127) as ubyte = { _
17 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
18 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
19 | 00, 00, 00, 00, 00, 00, 00, 00, 96, 97, _
20 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
21 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
22 | 00, 00, 00, 99, 00, 00, 100, 00, 00, 00, _
23 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
24 | 00, 102, 103, 104, 00, 105, 00, 106, 00, 107, _
25 | 108, 109, 110, 111, 00, 00, 00, 00, 00, 00, _
26 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
27 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
28 | 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, _
29 | 00, 00, 00, 00, 00, 00, 00, 00 }
30 |
31 | function scancode_to_keycode (set as integer, scancode as ushort) as ubyte
32 | dim keycode as ubyte = 0
33 |
34 | select case (set)
35 | case 0:
36 | '' normal scancode
37 | keycode = scancode_table(scancode)
38 | case 1:
39 | '' e0-code
40 | keycode = e0code_table(scancode)
41 | case 2:
42 | '' e1-code
43 | select case (scancode)
44 | case &h451D:
45 | keycode = 119
46 | case else:
47 | keycode = 0
48 | end select
49 | case else
50 | keycode = 0
51 | end select
52 |
53 | if (keycode = 0) then
54 | '' TODO: unknown scancode - print warning or something
55 | end if
56 |
57 | return keycode
58 | end function
59 |
--------------------------------------------------------------------------------
/kernel/src/cpu.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "cpu.bi"
20 | #include "kernel.bi"
21 | #include "mem.bi"
22 |
23 | sub cpu_get_vendor (zstr as zstring ptr)
24 | asm
25 | mov eax, 0
26 | cpuid
27 | mov eax, dword ptr [zstr]
28 | mov dword ptr [eax], ebx
29 | mov dword ptr [eax+4], edx
30 | mov dword ptr [eax+8], ecx
31 | end asm
32 | end sub
33 |
34 | function cpu_has_local_apic () as boolean
35 | dim t_edx as uinteger
36 | asm
37 | mov eax, 1
38 | cpuid
39 | mov dword ptr [t_edx], edx
40 | end asm
41 |
42 | return iif((t_edx and (1 shl 9)), true, false)
43 | end function
44 |
45 | function cpu_supports_PGE () as boolean
46 | dim t_edx as uinteger
47 | asm
48 | mov eax, 1
49 | cpuid
50 | mov dword ptr [t_edx], edx
51 | end asm
52 |
53 | return iif((t_edx and (1 shl 13)), true, false)
54 | end function
55 |
56 | function read_msr (msr as uinteger) as ulongint
57 | dim a as uinteger
58 | dim d as uinteger
59 |
60 | asm
61 | mov ecx, [msr]
62 |
63 | rdmsr
64 |
65 | mov [a], eax
66 | mov [d], edx
67 | end asm
68 |
69 | return (cast(ulongint, d) shl 32) or a
70 | end function
71 |
72 | sub write_msr (msr as uinteger, value as ulongint)
73 | dim a as uinteger = cuint(value)
74 | dim d as uinteger = cuint(value shr 32)
75 |
76 | asm
77 | mov ecx, [msr]
78 | mov eax, [a]
79 | mov edx, [d]
80 |
81 | wrmsr
82 | end asm
83 | end sub
84 |
85 | sub cpu_halt ()
86 | asm
87 | cli
88 | hlt_hlt:
89 | hlt
90 | jmp hlt_hlt
91 | end asm
92 | end sub
93 |
94 | sub cpu_disable_interrupts ()
95 | asm cli
96 | end sub
97 |
--------------------------------------------------------------------------------
/kernel/src/string_tokenizer.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "string_tokenizer.bi"
20 | #include "kmm.bi"
21 | #include "mem.bi"
22 | #include "zstring.bi"
23 |
24 | constructor StringTokenizer (s as zstring ptr)
25 | this.original_string = kmalloc(zstring_len(*s)+1)
26 | memcpy(this.original_string, s, zstring_len(*s)+1)
27 | string_iterator = original_string
28 | end constructor
29 |
30 | destructor StringTokenizer ()
31 | if (original_string <> 0) then
32 | kfree(this.original_string)
33 | end if
34 | end destructor
35 |
36 | function StringTokenizer.getToken (delimiters as zstring ptr) as zstring ptr
37 | if string_iterator = 0 then return 0
38 |
39 | '' skip leading delimiters
40 | dim delim_it as ubyte ptr = delimiters
41 | while (*delim_it <> 0 and *string_iterator <> 0)
42 | if (*string_iterator = *delim_it) then
43 | string_iterator += 1
44 | delim_it = delimiters
45 | else
46 | delim_it += 1
47 | end if
48 | wend
49 |
50 | '' did we reach the end of the string already?
51 | if *string_iterator = 0 then return 0
52 |
53 | function = string_iterator
54 |
55 | '' scan for the next delimiter
56 | while (*string_iterator <> 0)
57 | delim_it = delimiters
58 |
59 | while (*delim_it <> 0)
60 | if (*string_iterator = *delim_it) then
61 | '' found delimiter, replace with zero
62 | *cast(byte ptr, string_iterator) = 0
63 |
64 | '' set starting point for next round
65 | string_iterator += 1
66 |
67 | '' done for now
68 | exit function
69 | end if
70 |
71 | delim_it += 1
72 | wend
73 |
74 | string_iterator += 1
75 | wend
76 |
77 | string_iterator = 0
78 | end function
79 |
--------------------------------------------------------------------------------
/kernel/src/zstring.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2014 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "zstring.bi"
20 | #include "kernel.bi"
21 |
22 | '' this function searches for the string-terminator (\0)
23 | '' to find out the length of the string
24 | function zstring_len (zstr as zstring) as uinteger
25 | dim counter as uinteger = 0
26 | while (zstr[counter] > 0)
27 | counter += 1
28 | wend
29 | return counter
30 | end function
31 |
32 | '' this is a simple function to find out if and where a string is containing another
33 | function zstring_instr (zstr as zstring, substr as zstring) as uinteger
34 | dim is_substring as boolean
35 | dim len_zstr as uinteger = zstring_len(zstr)
36 | dim len_substr as uinteger = zstring_len(substr)
37 |
38 | if (len_zstr < len_substr) then return 0
39 |
40 | for counter as uinteger = 0 to len_zstr-len_substr
41 | is_substring = true
42 | for substring_length as uinteger = 0 to len_substr-1
43 | if (zstr[counter+substring_length] <> substr[substring_length]) then is_substring = false
44 | next
45 | if (is_substring) then return counter+1
46 | next
47 |
48 | return 0
49 | end function
50 |
51 | function zstring_cmp (zstr1 as zstring, zstr2 as zstring) as integer
52 | dim c as uinteger = 0
53 | while (zstr1[c] = zstr2[c])
54 | if (zstr1[c] = 0) then return 0
55 | c += 1
56 | wend
57 |
58 | return zstr1[c] - zstr2[c]
59 | end function
60 |
61 | function zstring_ncmp (zstr1 as zstring, zstr2 as zstring, n as uinteger) as integer
62 | dim c as uinteger = 0
63 |
64 | while (c zstr2[c]) then return (zstr1[c] - zstr2[c])
66 | if (zstr1[c] = 0) then exit while
67 | c += 1
68 | wend
69 |
70 | return 0
71 | end function
72 |
--------------------------------------------------------------------------------
/kernel/src/arch/x86/trampoline.asm.embedd:
--------------------------------------------------------------------------------
1 | ; FROST x86 microkernel
2 | ; Copyright (C) 2010-2017 Stefan Schmidt
3 | ;
4 | ; This program is free software: you can redistribute it and/or modify
5 | ; it under the terms of the GNU General Public License as published by
6 | ; the Free Software Foundation, either version 3 of the License, or
7 | ; (at your option) any later version.
8 | ;
9 | ; This program is distributed in the hope that it will be useful,
10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | ; GNU General Public License for more details.
13 | ;
14 | ; You should have received a copy of the GNU General Public License
15 | ; along with this program. If not, see .
16 |
17 | ; Code is copied to the first usable page (according to the osdev.org memory map)
18 | org 0x1000
19 |
20 | ; APs start in Real Mode, so 16bit code here
21 | BITS 16
22 |
23 | trampoline_entry:
24 | ; disable interrupts (just to be safe)
25 | cli
26 |
27 | ; load very basic GDT (replaced with a proper one later)
28 | lgdt [simplifiedGDTref]
29 |
30 | ; set Protected Mode bit
31 | mov eax, cr0
32 | or al, 1
33 | mov cr0, eax
34 |
35 | ; jump into Protected Mode
36 | jmp 08h:protectedMode
37 |
38 | simplifiedGDT:
39 | ; null-descriptor
40 | dw 0x0000
41 | dw 0x0000
42 | dw 0x0000
43 | dw 0x0000
44 |
45 | ; code-descriptor
46 | dw 0xFFFF
47 | dw 0x0000
48 | dw 0x9800
49 | dw 0x00CF
50 |
51 | ; data-descriptor
52 | dw 0xFFFF
53 | dw 0x0000
54 | dw 0x9200
55 | dw 0x00CF
56 |
57 | simplifiedGDTref:
58 | dw simplifiedGDTref-simplifiedGDT-1 ; size
59 | dd simplifiedGDT ; start address of the GDT
60 |
61 |
62 | ; Protected Mode code from this point on
63 | BITS 32
64 |
65 | protectedMode:
66 | ; cs is already set by the far jump, set remaining segment registers
67 | mov ax, 0x10
68 | mov ds, ax
69 | mov es, ax
70 | mov fs, ax
71 | mov gs, ax
72 | mov ss, ax
73 |
74 | ; we're free to do whatever we want from here
75 |
76 | ; for now, we print a plus on the serial port
77 | ; doesn't work properly on bochs though, because we don't check if the
78 | ; controller is ready, and boch doesn't like that
79 | mov al, 0x2b
80 | mov dx, 0x03F8
81 | out dx, al
82 |
83 | ; switch on paging here, or in kernel?
84 | ; where do we get a stack from?
85 | ; how do we signal we're ready?
86 |
87 | cli
88 | halt:
89 | hlt
90 | jmp halt
91 |
--------------------------------------------------------------------------------
/kernel/src/pmm_dma24.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "pmm.bi"
20 | #include "spinlock.bi"
21 | #include "kernel.bi"
22 | #include "mem.bi"
23 | #include "panic.bi"
24 |
25 | '' NOTE: As long as we just allocate with PAGE_SIZE-granularity, we
26 | '' could use a 'start looking here' pointer to reduce allocation time
27 |
28 | const bits_per_word = sizeof(uinteger)*8
29 | const bitmap_size = 16*1024*1024\PAGE_SIZE\bits_per_word
30 | '' memory bitmap for 0-16MB. 0=used, 1=free
31 | dim shared bitmap (0 to bitmap_size-1) as uinteger
32 | dim shared pmm_dma24_lock as spinlock
33 |
34 |
35 | sub pmm_init_dma24 ()
36 | '' mark the whole memory as occupied
37 | memset(@bitmap(0), 0, bitmap_size*sizeof(uinteger))
38 | end sub
39 |
40 | function pmm_alloc_dma24 () as any ptr
41 | pmm_dma24_lock.acquire()
42 |
43 | for counter as uinteger = lbound(bitmap) to ubound(bitmap)
44 | if (bitmap(counter) = 0) then continue for
45 |
46 | for bitcounter as uinteger = 0 to bits_per_word-1
47 | if (bitmap(counter) and (1 shl bitcounter)) then
48 | '' this page is free
49 | '' mark used
50 | bitmap(counter) and= (not(1 shl bitcounter))
51 | '' return page address
52 | pmm_dma24_lock.release()
53 | return cast(any ptr, (counter*bits_per_word + bitcounter)*PAGE_SIZE)
54 | end if
55 | next
56 | next
57 |
58 | '' no free page found?
59 | pmm_dma24_lock.release()
60 | panic_error(!"PMM_DMA24: Out of memory!\n")
61 | return nullptr
62 | end function
63 |
64 | sub pmm_free_dma24 (page as any ptr)
65 | pmm_dma24_lock.acquire()
66 |
67 | dim p as uinteger = cuint(page) \ PAGE_SIZE
68 |
69 | dim index as uinteger = p \ bits_per_word
70 | dim modifier as uinteger = (1 shl (p mod bits_per_word))
71 |
72 | assert((bitmap(index) and modifier) = 0) '' make sure that the page really was occupied
73 |
74 | bitmap(index) or= modifier
75 |
76 | pmm_dma24_lock.release()
77 | end sub
78 |
--------------------------------------------------------------------------------
/kernel/src/process.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "process.bi"
20 | #include "pmm.bi"
21 | #include "isf.bi"
22 | #include "vmm.bi"
23 | #include "kmm.bi"
24 | #include "mem.bi"
25 | #include "elf32.bi"
26 | #include "video.bi"
27 | #include "kernel.bi"
28 | #include "spinlock.bi"
29 | #include "panic.bi"
30 |
31 | DEFINE_LIST(process_type)
32 |
33 | function generate_pid () as uinteger
34 | static next_pid as uinteger = 0 '' next process id to assign
35 | static pid_lock as spinlock '' spinlock to protect concurrent access
36 |
37 | dim pid as uinteger '' the generated pid
38 |
39 | pid_lock.acquire() '' acquire lock
40 | pid = next_pid '' save pid
41 | next_pid += 1 '' increase pid counter
42 | pid_lock.release() '' release lock
43 |
44 | return pid '' return generated pid
45 | end function
46 |
47 | dim shared processlist as Listtype(process_type)
48 |
49 | operator process_type.new (size as uinteger) as any ptr
50 | return kmalloc(size)
51 | '' constructor is called automatically
52 | end operator
53 |
54 | operator process_type.delete (buffer as any ptr)
55 | kfree(buffer)
56 | '' destructor is called automatically
57 | end operator
58 |
59 | constructor process_type (parent as process_type ptr = 0)
60 | '' assign a process-ID
61 | this.id = generate_pid()
62 |
63 | '' set parent
64 | this.parent = parent
65 |
66 | this.ipc_handler = nullptr
67 | this.io_bitmap = nullptr
68 |
69 | '' insert the process into the list
70 | processlist.insert_before(@this.process_list)
71 |
72 | '' create a vmm-context
73 | vmm_context_initialize(@this.context)
74 | end constructor
75 |
76 | function process_type.get_tid () as uinteger
77 | this.tid_lock.acquire()
78 |
79 | function = this.next_tid
80 | this.next_tid += 1
81 |
82 | this.tid_lock.release()
83 | end function
84 |
85 | sub process_remove_thread (thread as thread_type ptr)
86 | thread->process_threads.remove()
87 | end sub
88 |
--------------------------------------------------------------------------------
/kernel/include/smp.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type smp_floating_pointer field=1
22 | signature as uinteger
23 | config_table as uinteger
24 | length as ubyte
25 | version as ubyte
26 | checksum as ubyte
27 | features(0 to 4) as ubyte
28 | end type
29 |
30 | type smp_config_table field=1
31 | signature as uinteger
32 | base_table_length as ushort
33 | spec_revision as ubyte
34 | checksum as ubyte
35 | oem_id as zstring*8
36 | product_id as zstring*12
37 | oem_table_ptr as uinteger
38 | oem_table_size as ushort
39 | entry_count as ushort
40 | local_apic_address as uinteger
41 |
42 | extended_table_length as ushort
43 | extended_table_checksum as ubyte
44 | reserved as ubyte
45 | end type
46 |
47 | enum CT_ENTRY_TYPES explicit
48 | PROCESSOR = 0
49 | BUS = 1
50 | IO_APIC = 2
51 | IO_INTERRUPT_ASSIGNMENT = 3
52 | LOCAL_INTERRUPT_ASSIGNMENT = 4
53 | end enum
54 |
55 |
56 | type cte_processor field=1
57 | entry_type as ubyte
58 | local_apic_id as ubyte
59 | local_apic_version as ubyte
60 | flags as ubyte
61 | signature as zstring*4
62 | feature_flags as uinteger
63 | reserved as ulongint
64 | end type
65 |
66 | type cte_bus field=1
67 | entry_type as ubyte
68 | bus_id as ubyte
69 | type_string as zstring*6
70 | end type
71 |
72 | type cte_io_apic field=1
73 | entry_type as ubyte
74 | id as ubyte
75 | version as ubyte
76 | flags as ubyte
77 | address as uinteger
78 | end type
79 |
80 | type cte_io_interrupt_assignment field=1
81 | entry_type as ubyte
82 | interrupt_type as ubyte
83 | flags as ushort
84 | bus_id as ubyte
85 | bus_irq as ubyte
86 | apic_id as ubyte
87 | apic_int as ubyte
88 | end type
89 |
90 | type cte_local_interrupt_assignment field=1
91 | entry_type as ubyte
92 | interrupt_type as ubyte
93 | flags as ushort
94 | bus_id as ubyte
95 | bus_irq as ubyte
96 | apic_id as ubyte
97 | apic_int as ubyte
98 | end type
99 |
100 | declare sub smp_init ()
101 |
--------------------------------------------------------------------------------
/kernel/include/vfs.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 | #include "intrusive_list.bi"
23 | #include "kmm.bi"
24 | #include "refcount_smartptr.bi"
25 | #include "uid128.bi"
26 |
27 | const VFS_FLAGS_KERNEL_NODE as integer = &h1
28 |
29 | type vfs_node as vfs_node_
30 | type __process_type as process_type
31 | type __thread_type as thread_type
32 |
33 | DECLARE_REFCOUNTPTR(vfs_node)
34 | DECLARE_LIST(vfs_node)
35 |
36 | type vfs_node_ extends RefCounted
37 | name as zstring ptr
38 |
39 | flags as integer
40 | permissions as integer
41 |
42 | uid as integer
43 | gid as integer
44 |
45 | union
46 | type
47 | owner as __process_type ptr
48 | handler as any ptr
49 | node_uid as uinteger
50 | end type
51 |
52 | mem as any ptr
53 | end union
54 |
55 | parent as vfs_node ptr
56 | child_list as Listtype(vfs_node)
57 | node_list as Listtype(vfs_node) = Listtype(vfs_node)(offsetof(vfs_node_, node_list))
58 |
59 | declare operator new (size as uinteger) as any ptr
60 | declare operator delete (buffer as any ptr)
61 | declare constructor (name as zstring ptr, parent as vfs_node ptr, flags as integer, owner as __process_type ptr = nullptr)
62 |
63 | declare function getChildByName (name as zstring) as RefCountPtr(vfs_node)
64 | end type
65 |
66 | DECLARE_LIST(vfs_fd)
67 | type vfs_fd
68 | id as uid128
69 | seekptr as uinteger<64>
70 | node as RefCountPtr(vfs_node)
71 |
72 | fd_list as Listtype(vfs_fd) = Listtype(vfs_fd)(offsetof(vfs_fd, fd_list))
73 |
74 | declare operator new (size as uinteger) as any ptr
75 | declare operator delete (buffer as any ptr)
76 | declare constructor (process as __process_type ptr, node as RefCountPtr(vfs_node))
77 | end type
78 |
79 | declare sub vfs_init ()
80 | declare function vfs_get_root as RefCountPtr(vfs_node)
81 | declare function vfs_parse_path (path as zstring) as RefCountPtr(vfs_node)
82 | declare function vfs_parse_path_afap (path as zstring) as RefCountPtr(vfs_node)
83 | declare function vfs_create (path as zstring ptr, name_ as zstring ptr, owner as __process_type ptr) as RefCountPtr(vfs_node)
84 | declare function vfs_open (thread as __thread_type ptr, path as zstring ptr, flags as uinteger) as vfs_fd ptr
85 |
--------------------------------------------------------------------------------
/kernel/src/pic.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "pic.bi"
20 | #include "in_out.bi"
21 | #include "kernel.bi"
22 |
23 | const MASTER_COMMAND as ubyte = &h20
24 | const MASTER_DATA as ubyte = &h21
25 | const SLAVE_COMMAND as ubyte = &hA0
26 | const SLAVE_DATA as ubyte = &hA1
27 |
28 | '' the end-of-interrupt command:
29 | const COMMAND_EOI as ubyte = &h20
30 |
31 | sub pic_init ()
32 | '' send ICW1 to both pics
33 | outb(MASTER_COMMAND, &h11)
34 | outb(SLAVE_COMMAND, &h11)
35 |
36 | '' ICW2 is where we want to map the interrupts
37 | '' we map them directly after the exceptions
38 | outb(MASTER_DATA, &h20)
39 | outb(SLAVE_DATA, &h28)
40 |
41 | '' ICW3: tell the PICs that they're connected through IRQ 2
42 | outb(MASTER_DATA, &h04)
43 | outb(SLAVE_DATA, &h02)
44 |
45 | '' ICW4: tell the PICs we're in 8086-mode
46 | outb(MASTER_DATA, &h01)
47 | outb(SLAVE_DATA, &h01)
48 |
49 | '' select ISR
50 | outb(MASTER_COMMAND, &h0B)
51 | outb(SLAVE_COMMAND, &h0B)
52 | end sub
53 |
54 | sub pic_send_eoi (irq as ubyte)
55 | outb(MASTER_COMMAND, COMMAND_EOI) '' send the EOI-command to the first PIC
56 | if (irq>7) then outb(SLAVE_COMMAND, COMMAND_EOI) '' if the irq was above 7, the second PIC needs to be informed also
57 | end sub
58 |
59 | function pic_is_spurious (irq as ubyte) as boolean
60 | if (irq = 7) then
61 | '' check ISR of the first pic
62 | if ((inb(MASTER_COMMAND) and &b10000000) = 0) then return true
63 | elseif (irq = 15) then
64 | '' check ISR of the second pic
65 | if ((inb(SLAVE_COMMAND) and &b10000000) = 0) then return true
66 | end if
67 |
68 | return false
69 | end function
70 |
71 | sub pic_mask (irq as ubyte)
72 | dim port as ushort
73 |
74 | if (irq < 8) then
75 | port = MASTER_DATA
76 | else
77 | port = SLAVE_DATA
78 | irq -= 8
79 | end if
80 |
81 | outb(port, (inb(port) or (1 shl irq)))
82 | end sub
83 |
84 | sub pic_mask_all ()
85 | outb(MASTER_DATA, &hFF)
86 | outb(SLAVE_DATA, &hFF)
87 | end sub
88 |
89 | sub pic_unmask (irq as ubyte)
90 | dim port as ushort
91 |
92 | if (irq < 8) then
93 | port = MASTER_DATA
94 | else
95 | port = SLAVE_DATA
96 | irq -= 8
97 | end if
98 |
99 | outb(port, (inb(port) and not(1 shl irq)))
100 | end sub
101 |
--------------------------------------------------------------------------------
/kernel/src/pmm_normal.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "pmm.bi"
20 | #include "spinlock.bi"
21 | #include "kernel.bi"
22 | #include "vmm.bi"
23 | #include "panic.bi"
24 |
25 | dim shared pmm_normal_lock as spinlock
26 |
27 | dim shared pmm_stack_min as uinteger ptr = cast(uinteger ptr, PMM_STACK_TOP)
28 | dim shared pmm_stack_ptr as uinteger ptr = cast(uinteger ptr, PMM_STACK_TOP)
29 | dim shared pmm_ready as boolean = false
30 |
31 | function pmm_alloc_normal () as any ptr
32 | if (not (pmm_ready and vmm_is_paging_ready())) then return nullptr '' let the request fall through
33 |
34 | if (pmm_stack_ptr = PMM_STACK_TOP) then return nullptr
35 |
36 | pmm_normal_lock.acquire()
37 |
38 | if (pmm_stack_ptr = (pmm_stack_min + PMM_STACK_ENTRIES_PER_PAGE)) then
39 | '' resolve page address
40 | function = vmm_resolve(vmm_get_current_context(), pmm_stack_min)
41 |
42 | '' unmap page
43 | vmm_unmap_page(vmm_get_current_context(), pmm_stack_min)
44 |
45 | '' adjust stack size
46 | pmm_stack_min += PMM_STACK_ENTRIES_PER_PAGE
47 | else
48 | if (vmm_is_paging_activated()) then
49 | function = cast(any ptr, *pmm_stack_ptr)
50 | else
51 | dim pmm_stack_ptr_phys as uinteger ptr = vmm_resolve(vmm_get_current_context(), pmm_stack_ptr)
52 | function = cast(any ptr, *pmm_stack_ptr_phys)
53 | end if
54 | pmm_stack_ptr += 1
55 | end if
56 |
57 | pmm_normal_lock.release()
58 | end function
59 |
60 | sub pmm_free_normal (addr as any ptr)
61 | '' make sure the address is page-aligned
62 | addr = cast(any ptr, cuint(addr) and VMM_PAGE_MASK)
63 |
64 | pmm_normal_lock.acquire()
65 |
66 | '' stack full?
67 | if (pmm_stack_ptr = pmm_stack_min) then
68 | vmm_map_page(vmm_get_current_context(), pmm_stack_min-PMM_STACK_ENTRIES_PER_PAGE, addr, VMM_FLAGS.KERNEL_DATA)
69 | pmm_stack_min -= PMM_STACK_ENTRIES_PER_PAGE
70 | assert(vmm_resolve(vmm_get_current_context(), pmm_stack_min) <> nullptr)
71 | else
72 | '' put the page on the stack
73 | pmm_stack_ptr -= 1
74 |
75 | if (vmm_is_paging_activated()) then
76 | *pmm_stack_ptr = cuint(addr)
77 | else
78 | dim pmm_stack_ptr_phys as uinteger ptr = vmm_resolve(vmm_get_current_context(), pmm_stack_ptr)
79 | assert(pmm_stack_ptr_phys <> nullptr)
80 | *pmm_stack_ptr_phys = cuint(addr)
81 | end if
82 | end if
83 |
84 | pmm_ready = true
85 |
86 | pmm_normal_lock.release()
87 | end sub
88 |
--------------------------------------------------------------------------------
/kernel/include/refcount_smartptr.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "atomic.bi"
22 |
23 | type RefCounted
24 | dim refcount as AtomicInt
25 | end type
26 |
27 |
28 | #define RefCountPtr(T_) RefCountPtr_##T_
29 |
30 | #macro DECLARE_REFCOUNTPTR(T_)
31 | type RefCountPtr(T_)
32 | ref as T_ ptr
33 |
34 | declare constructor ()
35 |
36 | '' construct from raw pointer
37 | declare constructor (reference as T_ ptr)
38 |
39 | '' copy-constructor
40 | declare constructor (reference as RefCountPtr(T_))
41 |
42 | '' clean-up destructor
43 | declare destructor ()
44 |
45 | declare operator let (byref rhs as RefCountPtr(T_))
46 |
47 | declare function get_count () as integer
48 | end type
49 | #endmacro
50 |
51 | #macro DEFINE_REFCOUNTPTR(T_)
52 | operator -> (byref tt_ as RefCountPtr(T_)) byref as T_
53 | assert(tt_.ref <> 0)
54 | return *tt_.ref
55 | end operator
56 |
57 | operator = (byref tt_ as RefCountPtr(T_), byref tt2_ as RefCountPtr(T_)) as integer
58 | if (tt_.ref = tt2_.ref) then return -1
59 | return 0
60 | end operator
61 |
62 | constructor RefCountPtr(T_) ()
63 | this.ref = 0
64 | end constructor
65 |
66 | constructor RefCountPtr(T_) (reference as T_ ptr)
67 | assert(reference <> 0)
68 | reference->refcount.inc()
69 | this.ref = reference
70 | end constructor
71 |
72 | constructor RefCountPtr(T_) (reference as RefCountPtr(T_))
73 | assert(reference.ref <> 0)
74 | reference.ref->refcount.inc()
75 | this.ref = reference.ref
76 | end constructor
77 |
78 | destructor RefCountPtr(T_) ()
79 | dim destroy as boolean = this.ref->refcount.sub_and_test(1)
80 |
81 | if (destroy) then
82 | delete this.ref
83 | end if
84 | end destructor
85 |
86 | operator RefCountPtr(T_).let (byref rhs as RefCountPtr(T_))
87 | if (this.ref <> 0) then
88 | dim destroy as boolean = this.ref->refcount.sub_and_test(1)
89 |
90 | if (destroy) then
91 | delete this.ref
92 | end if
93 | end if
94 |
95 | rhs.ref->refcount.inc()
96 | this.ref = rhs.ref
97 | end operator
98 |
99 |
100 | function RefCountPtr(T_).get_count () as integer
101 | return this.ref->refcount.get()
102 | end function
103 | #endmacro
104 |
--------------------------------------------------------------------------------
/kernel/include/thread.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "isf.bi"
22 | #include "intrusive_list.bi"
23 | #include "address_space.bi"
24 |
25 | const THREAD_STATE_DISABLED = 0
26 | const THREAD_STATE_RUNNING = 1
27 | const THREAD_STATE_BLOCKED = 2
28 | const THREAD_STATE_KILL_ON_SCHEDULE = 3
29 |
30 | const THREAD_FLAG_POPUP = 1
31 | const THREAD_FLAG_RESCHEDULE = 2
32 | const THREAD_FLAG_TRIGGERS_CALLBACK = 4
33 |
34 | DECLARE_LIST(thread_type)
35 |
36 | type process_type_ as process_type
37 |
38 | '' FIXME: what if process that requested the callback exits in the meantime? We would break this code!
39 | '' - making processes reference-counted would be an option
40 | '' - or maybe a 'callbacks-pending' variable that gets checked before destruction?
41 | '' FIXME: also, how do we make sure the callback always gets triggered, even when the popup-thread misbehaves?
42 | type callback_info_t
43 | process as process_type_ ptr '*< the process which receives the callback
44 | handle as uinteger '*< a caller-defined handle which gets passed to the callback
45 | callback as any ptr '*< the address of a function that gets called as a callback
46 | end type
47 |
48 | type thread_type
49 | parent_process as process_type_ ptr
50 |
51 | id as uinteger
52 | flags as uinteger
53 | state as uinteger
54 |
55 | kernelstack_p as any ptr
56 | kernelstack_bottom as any ptr
57 | stack_area as address_space_area ptr
58 | isf as interrupt_stack_frame ptr
59 |
60 | '' list of threads of a process
61 | process_threads as Listtype(thread_type) = Listtype(thread_type)(offsetof(thread_type, process_threads))
62 |
63 | '' list of active threads
64 | active_threads as Listtype(thread_type) = Listtype(thread_type)(offsetof(thread_type, active_threads))
65 |
66 | declare operator new (size as uinteger) as any ptr
67 | declare operator new[] (size as uinteger) as any ptr
68 | declare operator delete (buffer as any ptr)
69 |
70 | declare constructor (process as process_type_ ptr, entry as any ptr, userstack_pages as uinteger, flags as ubyte = 0)
71 | declare sub activate ()
72 | declare sub deactivate ()
73 | declare sub destroy ()
74 |
75 | callback_info as callback_info_t
76 |
77 | end type
78 |
79 | declare function schedule (isf as interrupt_stack_frame ptr) as thread_type ptr
80 | declare sub thread_switch (isf as interrupt_stack_frame ptr)
81 | declare function get_current_thread () as thread_type ptr
82 | declare sub thread_create_idle_thread ()
83 | declare sub set_io_bitmap ()
84 |
--------------------------------------------------------------------------------
/kernel/src/debug.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "debug.bi"
20 | #include "kernel.bi"
21 | #include "video.bi"
22 | #include "in_out.bi"
23 |
24 |
25 | '' this function allows a loglevel to be set which is used by a wrapper for the video-code
26 | sub debug_set_loglevel (level as ubyte)
27 | debug_loglevel = level
28 | end sub
29 |
30 | #if defined (FROST_DEBUG)
31 | dim shared debug_com_initialized as boolean = false
32 | dim shared COM1_PORT as ushort = &h3F8
33 |
34 | const REG_IER as ushort = 1 '' [RW] Interrupt Enable Register
35 | const REG_IIR as ushort = 2 '' [R ] Interrupt Identification Register
36 | const REG_FCR as ushort = 2 '' [ W] FIFO Control Register
37 | const REG_LCR as ushort = 3 '' [RW] Line Control Register
38 | const REG_MCR as ushort = 4 '' [RW] Modem Control Register
39 | const REG_LSR as ushort = 5 '' [R ] Line Status Register
40 | const REG_MSR as ushort = 6 '' [R ] Modem Status Register
41 | const REG_SCR as ushort = 7 '' [RW] Scratch Register
42 |
43 | sub debug_init_com (baud as uinteger, parity as ubyte, bits as ubyte)
44 | dim divisor as ushort = 115200\baud
45 |
46 | '' DLAB=1
47 | outb(COM1_PORT+REG_LCR, &h80)
48 |
49 | '' set baud rate divisor
50 | outb(COM1_PORT, lobyte(divisor))
51 | outb(COM1_PORT+REG_IER, hibyte(divisor))
52 |
53 | '' set parity, bits-per-byte and DLAB=0
54 | outb(COM1_PORT+REG_LCR, ((parity and &h07) shl 3) or ((bits-5) and &h03))
55 |
56 | '' no interrupts
57 | outb(COM1_PORT+REG_IER, 0)
58 |
59 | '' disable FIFOs
60 | outb(COM1_PORT+REG_FCR, &h00)
61 |
62 | '' disable AUX & loopback
63 | outb(COM1_PORT+REG_MCR, &h00)
64 | end sub
65 |
66 | sub debug_serial_init ()
67 | debug_init_com(19200, 0, 8)
68 | debug_com_initialized = true
69 | end sub
70 |
71 | sub debug_serial_putc (char as ubyte)
72 | '' typical terminal software requires a carriage return, too
73 | if (char = 10) then
74 | debug_serial_putc(13)
75 | end if
76 |
77 | if (debug_com_initialized) then
78 | '' wait until we can write
79 | while((inb(COM1_PORT+REG_LSR) and &h20) = 0) : wend
80 | '' write byte
81 | outb(COM1_PORT, char)
82 | end if
83 | end sub
84 | #endif
85 |
86 | sub debug_stacktrace (maxFrames as uinteger)
87 | dim ebp as uinteger ptr = @maxFrames -2
88 |
89 | ebp = cast(uinteger ptr, ebp)
90 |
91 | printk(LOG_ERR !"stacktrace\n")
92 | for frame as uinteger = 0 to maxFrames
93 | dim eip as uinteger = ebp[1]
94 |
95 | if (eip = 0) or (ebp = nullptr) then
96 | exit for
97 | end if
98 |
99 | ebp = cast(uinteger ptr, ebp[0])
100 | printk(LOG_ERR !" 0x%08X\n", eip)
101 | next
102 | end sub
103 |
--------------------------------------------------------------------------------
/kernel/src/io_man.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "kernel.bi"
20 | #include "process.bi"
21 | #include "kmm.bi"
22 | #include "mem.bi"
23 | #include "video.bi"
24 |
25 | dim shared global_port_bitmap(0 to 2047) as uinteger
26 |
27 | sub init_ports ()
28 | asm
29 | pushf
30 | pop eax
31 | and eax, &hFFFFCFFF
32 | push eax
33 | popf
34 | end asm
35 |
36 | memset(@global_port_bitmap(0), 0, sizeof(uinteger)*2048)
37 | end sub
38 |
39 | function request_port (process as process_type ptr, port as uinteger) as boolean
40 | dim index as uinteger = port \ 32
41 | dim mask as uinteger = 1 shl (port mod 32)
42 |
43 | '' port out of range?
44 | if (port >= &hFFFF) then
45 | return false
46 | end if
47 |
48 | '' port free ?
49 | if (global_port_bitmap(index) and mask) then
50 | '' port not reserved for this process?
51 | if ((process->io_bitmap <> nullptr) and process->io_bitmap[index] and mask) then
52 | return false
53 | else
54 | return true
55 | end if
56 | end if
57 |
58 | '' if there is no bitmap yet, reserve one
59 | if (process->io_bitmap = nullptr) then
60 | process->io_bitmap = kmalloc(&hFFFF \ 8)
61 | memset(process->io_bitmap, &hFF, &hFFFF \ 8)
62 | end if
63 |
64 | '' reserve the port
65 | global_port_bitmap(index) or= mask
66 | process->io_bitmap[index] and= not mask
67 |
68 | return true
69 | end function
70 |
71 | function release_port (process as process_type ptr, port as uinteger) as boolean
72 | dim index as uinteger = port \ 32
73 | dim mask as uinteger = 1 shl (port mod 32)
74 |
75 | if (process->io_bitmap = nullptr) then return false
76 |
77 | if (process->io_bitmap[index] and mask) then return false
78 |
79 | assert((global_port_bitmap(index) and mask) > 0)
80 |
81 | global_port_bitmap(index) and= not mask
82 | process->io_bitmap[index] or= mask
83 |
84 | return true
85 | end function
86 |
87 | function request_port_range (process as process_type ptr, start_port as uinteger, length as uinteger) as boolean
88 | for port_counter as uinteger = start_port to start_port+length
89 | if (not request_port(process, port_counter)) then
90 | for port_counter2 as uinteger = port_counter to start_port step -1
91 | release_port(process, port_counter2)
92 | return false
93 | next
94 | end if
95 | next
96 |
97 | return true
98 | end function
99 |
100 | function release_port_range (process as process_type ptr, start_port as uinteger, length as uinteger) as boolean
101 | function=true
102 | for port_counter as uinteger = start_port to start_port+length
103 | if (not release_port(process, port_counter)) then function=false
104 | next
105 | end function
106 |
--------------------------------------------------------------------------------
/kernel/src/stubs.asm:
--------------------------------------------------------------------------------
1 | ; FROST x86 microkernel
2 | ; Copyright (C) 2010-2017 Stefan Schmidt
3 | ;
4 | ; This program is free software: you can redistribute it and/or modify
5 | ; it under the terms of the GNU General Public License as published by
6 | ; the Free Software Foundation, either version 3 of the License, or
7 | ; (at your option) any later version.
8 | ;
9 | ; This program is distributed in the hope that it will be useful,
10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | ; GNU General Public License for more details.
13 | ;
14 | ; You should have received a copy of the GNU General Public License
15 | ; along with this program. If not, see .
16 |
17 | ; This file is to provide stubs for the exceptions and irqs
18 | ; which then call the interrupt handler of the kernel
19 | section .text
20 |
21 | extern HANDLE_INTERRUPT
22 |
23 | ; some ints push a errorcode on the stack
24 | ; the handler for ints which do not do that pushes a zero to the stack to make the stack look equal
25 | %macro int_stub 1
26 | global INT_STUB_%1
27 | INT_STUB_%1:
28 | %if (%1 != 8) && (%1 < 10 || %1 > 14) && (%1 != 17)
29 | push dword 0
30 | %endif
31 | push dword %1
32 | jmp int_common
33 | %endmacro
34 |
35 | ; create all 256 stubs (0-255)
36 | %assign stub_counter 0
37 | %rep 256
38 | int_stub stub_counter
39 | %assign stub_counter stub_counter+1
40 | %endrep
41 |
42 | extern HANDLE_INTERRUPT
43 | global SYSENTER_ENTRY
44 |
45 | int_common:
46 | ; save the registers
47 | push ebp
48 | push edi
49 | push esi
50 | push edx
51 | push ecx
52 | push ebx
53 | push eax
54 |
55 | ; load the ring-0 segment-registers
56 | mov ax, 0x10
57 | mov ds, ax
58 | mov es, ax
59 |
60 | push dword 0
61 |
62 | ; now call the handler
63 | push esp ; push the old stack address
64 | call HANDLE_INTERRUPT ; call the interrupt-handler written in FreeBASIC
65 | mov esp, eax ; set the new stack address
66 |
67 | pop ebx
68 | test ebx, ebx
69 | jne SYSENTER_EXIT
70 |
71 | int_exit:
72 | ; load the ring-3 segment-registers
73 | mov ax, 0x23
74 | mov ds, ax
75 | mov es, ax
76 |
77 | ; restore the old state
78 | pop eax
79 | pop ebx
80 | pop ecx
81 | pop edx
82 | pop esi
83 | pop edi
84 | pop ebp
85 |
86 | ; skip the errorcode and the interrupt-number
87 | add esp, 8
88 |
89 | ; now we return
90 | iret
91 |
92 |
93 | section .text
94 | SYSENTER_ENTRY:
95 | ; We make the stack look like an x86 interrupt-stackframe
96 | sub esp, 24
97 | push dword 0xFF
98 |
99 | push ebp
100 | push edi
101 | push esi
102 | push edx
103 | push ecx
104 | push ebx
105 | push eax
106 |
107 | push dword 1
108 |
109 | push esp
110 | call HANDLE_INTERRUPT
111 | mov esp, eax
112 |
113 | pop ebx
114 | test ebx, ebx
115 | je int_exit
116 |
117 | SYSENTER_EXIT:
118 | pop eax
119 | pop ebx
120 | pop ecx
121 | pop edx
122 | pop esi
123 | pop edi
124 | pop ebp
125 |
126 | add esp, 28
127 |
128 | ; SYSENTER clears the interrupt-flag in EFLAGS without saving,
129 | ; so we set it again with sti. sti has a delay of one instruction,
130 | ; so it's impossible we get interrupted before sysexit.
131 | sti
132 | sysexit
133 |
--------------------------------------------------------------------------------
/kernel/include/vmm.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #include "kernel.bi"
22 |
23 | #define num_pages(n) (((n + &hFFF) and (&hFFFFF000)) shr 12)
24 |
25 | '' flags for page-table-entries
26 | enum VMM_PTE_FLAGS explicit
27 | PRESENT = &h1
28 | WRITABLE = &h2
29 | USERSPACE = &h4
30 | WRITETHROUGH = &h8
31 | NOT_CACHEABLE = &h10
32 | ACCESSED = &h20
33 | DIRTY = &h40
34 | PAT = &h80
35 | GLOBAL = &h100
36 | end enum
37 |
38 | '' flags for page-directory-entries
39 | enum VMM_PDE_FLAGS explicit
40 | PRESENT = &h1
41 | WRITABLE = &h2
42 | USERSPACE = &h4
43 | WRITETHROUGH = &h8
44 | NOT_CACHEABLE = &h10
45 | ACCESSED = &h20
46 | DIRTY = &h40
47 | FOUR_MB = &h80
48 | GLOBAL = &h100
49 | end enum
50 |
51 | enum VMM_FLAGS explicit
52 | USER_DATA = VMM_PTE_FLAGS.PRESENT or VMM_PTE_FLAGS.WRITABLE or VMM_PTE_FLAGS.USERSPACE
53 | KERNEL_DATA = VMM_PTE_FLAGS.PRESENT or VMM_PTE_FLAGS.WRITABLE or VMM_PTE_FLAGS.GLOBAL
54 | end enum
55 |
56 | '' the kernels address space is from 0-1 gb, so we put the kernels pagetables at 1gb-4mb
57 | const VMM_PAGETABLES_VIRT_START as uinteger = &h3FC00000
58 | const VMM_PAGE_MASK as uinteger = &hFFFFF000
59 |
60 | type vmm_context
61 | version as uinteger '' important to keep the kernel section up to date
62 | p_pagedir as uinteger ptr '' physical address of the pagedir, needed for the cpu
63 | v_pagedir as uinteger ptr '' virtual address of the pagedir, needed to access the pagedir later
64 | end type
65 |
66 | declare sub vmm_init ()
67 | declare sub vmm_init_local ()
68 | declare function vmm_alloc (v_addr as any ptr) as boolean
69 | declare sub vmm_context_initialize (cntxt as vmm_context ptr)
70 | declare function vmm_map_page (cntxt as vmm_context ptr, virtual as any ptr, physical as any ptr, flags as uinteger) as boolean
71 | declare sub vmm_unmap_page (cntxt as vmm_context ptr, v_addr as any ptr)
72 | declare function vmm_map_range (cntxt as vmm_context ptr, v_addr as any ptr, p_start as any ptr, p_end as any ptr, flags as uinteger) as boolean
73 | declare sub vmm_unmap_range (cntxt as vmm_context ptr, v_addr as any ptr, pages as uinteger)
74 | declare function vmm_automap (context as vmm_context ptr, p_start as any ptr, size as uinteger, lowerLimit as uinteger, upperLimit as uinteger, flags as uinteger) as any ptr
75 | declare function vmm_kernel_automap (p_start as any ptr, size as uinteger, flags as uinteger = VMM_FLAGS.KERNEL_DATA) as any ptr
76 | declare sub vmm_kernel_unmap (v_start as any ptr, size as uinteger)
77 | declare function vmm_resolve (cntxt as vmm_context ptr, vaddr as any ptr) as any ptr
78 | declare sub vmm_activate_context (cntxt as vmm_context ptr)
79 | declare function vmm_get_current_context () as vmm_context ptr
80 | declare function vmm_is_paging_activated () as boolean
81 | declare function vmm_is_paging_ready () as boolean
82 |
--------------------------------------------------------------------------------
/kernel/src/interrupt.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "apic.bi"
20 | #include "pic.bi"
21 | #include "cpu.bi"
22 | #include "interrupt.bi"
23 |
24 | dim shared legacy_mode as boolean = true
25 | dim shared interrupt_legacy_free as boolean = false
26 |
27 | sub interrupt_init ()
28 | if (cpu_has_local_apic()) then
29 | legacy_mode = false
30 |
31 | '' the ACPI-code sets this variable when the 8259-PIC-flag in the MADT is not set
32 | if (not interrupt_legacy_free) then
33 | pic_init()
34 | pic_mask_all()
35 | end if
36 |
37 | lapic_init()
38 | ioapic_init()
39 | return
40 | end if
41 |
42 | pic_init()
43 | pic_mask_all()
44 | end sub
45 |
46 | sub interrupt_mask (interrupt as integer)
47 | if (legacy_mode) then
48 | '' ignore non-IRQs
49 | if ((interrupt < &h20) or (interrupt > &h2F)) then return
50 |
51 | pic_mask(interrupt - &h20)
52 | return
53 | end if
54 |
55 | if (interrupt < &h20) then return
56 | ioapic_mask_irq(interrupt-&h20)
57 | end sub
58 |
59 | sub interrupt_unmask (interrupt as integer)
60 | if (legacy_mode) then
61 | '' ignore non-IRQs
62 | if ((interrupt < &h20) or (interrupt > &h2F)) then return
63 |
64 | pic_unmask(interrupt - &h20)
65 | return
66 | end if
67 |
68 | if (interrupt < &h20) then return
69 | ioapic_unmask_irq(interrupt-&h20)
70 | end sub
71 |
72 | function interrupt_is_spurious (interrupt as integer) as boolean
73 | if (legacy_mode) then
74 | '' ignore non-IRQs
75 | if ((interrupt < &h20) or (interrupt > &h2F)) then return false
76 |
77 | return pic_is_spurious(interrupt - &h20)
78 | end if
79 |
80 | '' is it a spurios I/O APIC interrupt?
81 | if (interrupt = &h2F) then return true
82 |
83 | '' could still be a spurious PIC-interrupt
84 | if (not interrupt_legacy_free) then return pic_is_spurious(interrupt - &h20)
85 |
86 | return false
87 | end function
88 |
89 | sub interrupt_eoi (interrupt as integer)
90 | if (legacy_mode) then
91 | '' ignore non-IRQs
92 | if ((interrupt < &h20) or (interrupt > &h2F)) then return
93 |
94 | if (interrupt_is_spurious(interrupt)) then
95 | '' did it come from the slave PIC? then send EOI to the master
96 | if (interrupt = &h2F) then pic_send_eoi(&h01)
97 | return
98 | end if
99 |
100 | pic_send_eoi(interrupt - &h20)
101 | return
102 | end if
103 |
104 | '' Volume 3A Chapter 10.9 says we shouldn't send the LAPIC an EOI when receiving a spurious interrupt
105 | '' also, since we don't need the PIC to get IRQs, we just ignore its spurious interrupts and send no EOI to it ever
106 | if (not(interrupt_is_spurious(interrupt))) then
107 | lapic_eoi()
108 | end if
109 | end sub
110 |
--------------------------------------------------------------------------------
/kernel/src/address_space.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "address_space.bi"
20 | #include "pmm.bi"
21 | #include "kmm.bi"
22 | #include "video.bi"
23 |
24 | DEFINE_LIST(address_space_area)
25 |
26 | constructor address_space_area (address as any ptr, pages as uinteger, flags as uinteger = 0, description as zstring ptr = nullptr)
27 | this.address = address
28 | this.pages = pages
29 | this.flags = flags
30 | this.description = description
31 | end constructor
32 |
33 | operator address_space_area.new (size as uinteger) as any ptr
34 | return kmalloc(size)
35 | end operator
36 |
37 | operator address_space_area.delete (buffer as any ptr)
38 | kfree(buffer)
39 | end operator
40 |
41 | function address_space.allocate_area (pages as uinteger, flags as uinteger = 0, description as zstring ptr = nullptr) as address_space_area ptr
42 | '' 1. search the list of areas for a free spot
43 | '' 2. create a new area and insert it in the list
44 | '' 3. return the address of the area
45 |
46 | dim min_addr as uinteger = &h40000000
47 | dim insert_after as Listtype(address_space_area) ptr = @this.areas
48 |
49 | list_foreach(h, this.areas)
50 | dim x as address_space_area ptr = h->get_owner()
51 |
52 | insert_after = h
53 |
54 | '' Is the hole big enough?
55 | if (x->address > min_addr + pages) then
56 | list_foreach_exit
57 | end if
58 |
59 | '' try the next hole
60 | min_addr = cuint(x->address) + x->pages * PAGE_SIZE
61 | list_next(h)
62 |
63 | '' Did we walk through the list and didn't find a hole yet?
64 | if ((min_addr <> &h40000000) and (insert_after <> @this.areas)) then
65 | '' check if there's space at the end
66 | dim x as address_space_area ptr = this.areas.get_prev()->get_owner()
67 | if (x->address + x->pages*PAGE_SIZE < &hFFFFFFFF - pages) then
68 | min_addr = cuint(x->address) + x->pages*PAGE_SIZE
69 | insert_after = this.areas.get_prev()
70 | else
71 | '' Nope, nothing's free
72 | return 0
73 | end if
74 | end if
75 |
76 | '' Create new struct
77 | dim area as address_space_area ptr = new address_space_area(cast(any ptr, min_addr), pages, flags, description)
78 |
79 | '' insert it
80 | insert_after->insert_after(@area->list)
81 |
82 | '' return the area address
83 | return area
84 | end function
85 |
86 | sub address_space.insert_area (area as address_space_area ptr)
87 | assert(area->pages <> 0)
88 | dim insert_after as Listtype(address_space_area) ptr = @this.areas
89 |
90 | list_foreach(h, this.areas)
91 | dim x as address_space_area ptr = h->get_owner()
92 |
93 | if (x->address > area->address) then
94 | '' check for overlaps
95 | assert(area->address+area->pages*PAGE_SIZE <= x->address)
96 |
97 | list_foreach_exit
98 | else
99 | '' check for overlaps
100 | assert(x->address+x->pages*PAGE_SIZE <= area->address)
101 | end if
102 |
103 | insert_after = h
104 | list_next(h)
105 |
106 | insert_after->insert_after(@area->list)
107 |
108 | end sub
109 |
--------------------------------------------------------------------------------
/kernel/src/modules.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "modules.bi"
20 | #include "multiboot.bi"
21 | #include "process.bi"
22 | #include "elf.bi"
23 | #include "kernel.bi"
24 | #include "panic.bi"
25 | #include "vmm.bi"
26 | #include "pmm.bi"
27 | #include "video.bi"
28 |
29 | declare sub load_module (multiboot_module as multiboot_module_t ptr, process as process_type ptr ptr)
30 |
31 | type module_list
32 | start as any ptr
33 | size as uinteger
34 | cmdline as any ptr
35 | end type
36 |
37 |
38 |
39 | 'dim shared init_process as process_type ptr
40 |
41 | sub load_init_module (mbinfo as multiboot_info ptr)
42 | '' if no modules are available, we have a problem
43 | if (mbinfo->mods_count = 0) then
44 | panic_error(!"No init-module available.\n")
45 | end if
46 |
47 | load_module(cast(multiboot_module_t ptr, mbinfo->mods_addr), @init_process)
48 |
49 | '' we loaded the module, so remove it from the list
50 | mbinfo->mods_addr += sizeof(multiboot_module_t)
51 | mbinfo->mods_count -= 1
52 | end sub
53 |
54 | sub load_modules (mbinfo as multiboot_info ptr)
55 | if (mbinfo->mods_count) = 0 then return
56 |
57 | dim mod_addr as multiboot_module_t ptr = cast(multiboot_module_t ptr, mbinfo->mods_addr)
58 |
59 | for index as uinteger = 0 to mbinfo->mods_count-1
60 | dim process as process_type ptr = nullptr
61 | load_module(mod_addr, @process)
62 |
63 | mod_addr += 1
64 | next
65 | end sub
66 |
67 |
68 | '' TODO: the cmdline should be given to the module somehow (e.g. do it like linux - /proc/pid/cmdline - we need vfs for this)
69 | sub load_module (multiboot_module as multiboot_module_t ptr, process as process_type ptr ptr)
70 | dim v_multiboot_module as multiboot_module_t ptr
71 |
72 | '' map the module structure
73 | v_multiboot_module = vmm_kernel_automap(multiboot_module, sizeof(multiboot_module_t))
74 | if (v_multiboot_module = 0) then
75 | panic_error(!"Could not map the module-structure of the module\n")
76 | end if
77 |
78 | '' map the image
79 | dim size as uinteger = v_multiboot_module->mod_end - v_multiboot_module->mod_start
80 | dim v_image as uinteger = cuint(vmm_kernel_automap(cast(any ptr, v_multiboot_module->mod_start), size))
81 |
82 | *process = new process_type()
83 |
84 | if (*process = nullptr) then
85 | panic_error(!"Could not create init-process!\n")
86 | end if
87 |
88 | dim thread as thread_type ptr
89 |
90 | if (not(elf_load_image(*process, @thread, v_image, size))) then
91 | panic_error(!"Could not load the init-module!")
92 | end if
93 |
94 | thread->activate()
95 |
96 | '' unmap the image, we don't need it any longer
97 | vmm_kernel_unmap(cast(any ptr, v_image), size)
98 |
99 | '' physically free the space occupied by the image
100 | for c as uinteger = 0 to num_pages(size)-1
101 | pmm_free(cast(any ptr, v_multiboot_module->mod_start + c*PAGE_SIZE))
102 | next
103 |
104 | '' unmap the module struct
105 | vmm_kernel_unmap(v_multiboot_module, sizeof(multiboot_module_t))
106 | end sub
107 |
108 | sub pass_modules_to_init (mbinfo as multiboot_info ptr)
109 | '' TODO:
110 | '' - map the multiboot-modules into init
111 | '' - create a list of modules in init
112 | '' - pass the address to init via the stack
113 | end sub
114 |
--------------------------------------------------------------------------------
/kernel/src/elf.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2015 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "elf.bi"
20 | #include "elf32.bi"
21 | #include "process.bi"
22 | #include "thread.bi"
23 | #include "pmm.bi"
24 | #include "mem.bi"
25 | #include "panic.bi"
26 |
27 | function elf_header_check (header as Elf32_Ehdr ptr) as integer
28 | '' check for the magic value (&h7F, 'E', 'L', 'F')
29 | if ((header->e_ident.EI_MAGIC(0) <> &h7F) or _
30 | (header->e_ident.EI_MAGIC(1) <> &h45) or _
31 | (header->e_ident.EI_MAGIC(2) <> &h4C) or _
32 | (header->e_ident.EI_MAGIC(3) <> &h46)) then return 1
33 |
34 | if (header->e_type <> ELF_ET_EXEC) then return 2
35 | if (header->e_machine <> ELF_EM_386) then return 3
36 | if (header->e_ident.EI_CLASS <> ELF_CLASS_32) then return 4
37 | if (header->e_ident.EI_DATA <> ELF_DATA_2LSB) then return 5
38 | if (header->e_version <> ELF_EV_CURRENT) then return 6
39 | return 0
40 | end function
41 |
42 |
43 | function elf_load_image (process as process_type ptr, thread as thread_type ptr ptr, image as uinteger, size as uinteger) as boolean
44 | dim header as Elf32_Ehdr ptr = cast(Elf32_Ehdr ptr, image)
45 |
46 | if (size < sizeof(Elf32_Ehdr)) then return false
47 |
48 | if (elf_header_check(header) > 0) then return false
49 |
50 | '' pointer to the first program header
51 | dim program_header as Elf32_Phdr ptr = cast(Elf32_Phdr ptr, cuint(header) + header->e_phoff)
52 |
53 | '' iterate over all segments
54 | for counter as uinteger = 0 to header->e_phnum-1
55 | '' skip segments that are not loadable
56 | if (program_header[counter].p_type <> ELF_PT_LOAD) then continue for
57 |
58 | '' align the start on page-boundaries
59 | dim start as uinteger = program_header[counter].p_vaddr and VMM_PAGE_MASK
60 | dim real_size as uinteger = program_header[counter].p_filesz + (program_header[counter].p_vaddr - start)
61 | dim real_mem_size as uinteger = program_header[counter].p_memsz + (program_header[counter].p_vaddr - start)
62 |
63 | '' start and end of the segment
64 | dim addr as uinteger = start
65 | dim end_addr as uinteger = start + real_size
66 | dim end_addr_mem as uinteger = start + real_mem_size
67 |
68 | dim area as address_space_area ptr = new address_space_area(cast(any ptr, start), num_pages(real_mem_size))
69 | process->a_s.insert_area(area)
70 |
71 |
72 | while (addr < end_addr_mem)
73 | dim phys_mem as any ptr = pmm_alloc()
74 | dim mem as any ptr = vmm_kernel_automap(phys_mem, PAGE_SIZE)
75 |
76 | if (addr < end_addr) then
77 | dim remaining_copy as uinteger = end_addr - addr
78 | dim chunk_size as uinteger = iif(remaining_copy > PAGE_SIZE, PAGE_SIZE, remaining_copy)
79 |
80 | memcpy(mem,_
81 | cast(any ptr, image + program_header[counter].p_offset + (addr-start)), _
82 | chunk_size)
83 |
84 | if (PAGE_SIZE - chunk_size > 0) then memset(mem+chunk_size, 0, PAGE_SIZE-chunk_size)
85 | else
86 | memset(mem, 0, PAGE_SIZE)
87 | end if
88 |
89 | vmm_kernel_unmap(mem, PAGE_SIZE)
90 |
91 | vmm_map_page(@process->context, cast(any ptr, addr), cast(any ptr, phys_mem), VMM_PTE_FLAGS.WRITABLE or VMM_PTE_FLAGS.PRESENT or VMM_PTE_FLAGS.USERSPACE)
92 |
93 | addr += PAGE_SIZE
94 | wend
95 | next
96 |
97 | '' create the thread
98 | *thread = new thread_type(process, cast(any ptr, header->e_entry), 1)
99 |
100 | return true
101 | end function
102 |
--------------------------------------------------------------------------------
/drivers/keyboard/src/main.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST
3 | ' Copyright (C) 2010-2018 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | '' PS/2 8042 keyboard controller driver
20 |
21 | #include "../../libfrost/frost.bi"
22 | #include "keyboard.bi"
23 |
24 | const KBC_COMMAND as ubyte = &h64
25 | const KBC_DATA as ubyte = &h60
26 |
27 | declare sub irq_handler (irq_number as uinteger)
28 | declare sub kbc_send_command (cmd as ubyte)
29 |
30 | sub outb (port as ushort, value as ubyte)
31 | asm
32 | movw dx, [port]
33 | movb al, [value]
34 | outb dx, al
35 | end asm
36 | end sub
37 |
38 | function inb (port as ushort) as ubyte
39 | asm
40 | movw dx, [port]
41 | inb al, dx
42 | mov [function], al
43 | end asm
44 | end function
45 |
46 | sub main ()
47 | '' request access to the controller's ports
48 | frost_syscall_port_request(KBC_COMMAND)
49 | frost_syscall_port_request(KBC_DATA)
50 |
51 | frost_syscall_irq_handler_register(1, @irq_handler)
52 |
53 | '' clear the buffer
54 | while ((inb(KBC_COMMAND) and &h01) <> 0)
55 | inb(KBC_DATA)
56 | wend
57 |
58 | '' turn the LEDs off
59 | kbc_send_command(&hED)
60 | kbc_send_command(&h00)
61 |
62 | '' activate the keyboard
63 | kbc_send_command(&hF4)
64 |
65 | frost_syscall_43(strptr("Keyboard controller initialized"))
66 |
67 | asm jmp $
68 | end sub
69 |
70 | sub irq_handler (irq_number as uinteger)
71 | while ((inb(KBC_COMMAND) and &h01) <> 0)
72 | if (irq_number = &h01) then
73 | dim is_break_code as integer = false
74 | dim keycode as ubyte
75 | static e0_code as integer = false
76 | static e1_code as integer = 0
77 | static e1_prev as ushort = 0
78 | dim scancode as ubyte = inb(KBC_DATA)
79 |
80 | if (bit(scancode, 7) and (e1_code or (scancode <> &hE1)) and (e0_code or (scancode <> &hE0))) then
81 | is_break_code = true
82 | scancode = bitreset(scancode, 7)
83 | end if
84 |
85 | if (e0_code) then
86 | '' catch fake-shift
87 | if ((scancode = &h2A) or (scancode = &h36)) then
88 | e0_code = false
89 | else
90 | keycode = scancode_to_keycode(1, scancode)
91 | e0_code = false
92 | end if
93 | elseif (e1_code = 2) then
94 | '' second (and last) byte of an e1-code
95 | e1_prev or= cushort(scancode) shl 8
96 | keycode = scancode_to_keycode(2, e1_prev)
97 | e1_code = 0
98 | elseif (e1_code = 1) then
99 | '' first byte of an e1-code
100 | e1_prev = scancode
101 | e1_code += 1
102 | elseif (scancode = &hE0) then
103 | '' beginning of an e0-code
104 | e0_code = true
105 | elseif (scancode = &hE1) then
106 | '' beginning of an e1-code
107 | e1_code = 1
108 | else
109 | '' normal scancode
110 | keycode = scancode_to_keycode(0, scancode)
111 | end if
112 |
113 | if (keycode <> 0) then
114 | if (is_break_code) then
115 | frost_syscall_43(strptr("Key released"))
116 | else
117 | frost_syscall_43(strptr("Key pressed"))
118 | end if
119 | end if
120 | end if
121 | wend
122 |
123 | frost_syscall_irq_handler_exit(irq_number)
124 | end sub
125 |
126 | sub kbc_send_command (cmd as ubyte)
127 | do
128 | '' wait until the input buffer is empty
129 | while ((inb(KBC_COMMAND) and &h02) <> 0)
130 | frost_syscall_thread_yield()
131 | wend
132 |
133 | outb(KBC_DATA, cmd)
134 |
135 | while ((inb(KBC_COMMAND) and &h01) = 0)
136 | frost_syscall_thread_yield()
137 | wend
138 | loop while (inb(KBC_DATA) = &hFE)
139 | end sub
140 |
--------------------------------------------------------------------------------
/kernel/include/intrusive_list.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | #define Listtype(T_) Listtype_##T_
22 |
23 | #macro DECLARE_LIST(T_)
24 | '' IMPORTANT: RefCountPtr needs to be declared BEFORE declaring the list!
25 | #if defined(RefCountPtr_##T_)
26 | '' this type seems to be refcounted!
27 | type Listtype_p_##T_ as RefCountPtr(T_)
28 | #define Listtype_r_##t_
29 | #else
30 | '' not refcounted, use normal pointer
31 | type Listtype_p_##T_ as T_ ptr
32 | #endif
33 |
34 |
35 | type Listtype_t_##T_ as T_
36 |
37 | type Listtype(T_)
38 | private:
39 | next_ptr as Listtype(T_) ptr
40 | prev_ptr as Listtype(T_) ptr
41 | owner as Listtype_p_##T_
42 | public:
43 | declare constructor (offset as uinteger)
44 | declare constructor ()
45 | declare destructor ()
46 | declare sub insert_after (new_head as Listtype(T_) ptr)
47 | declare sub insert_before (new_head as Listtype(T_) ptr)
48 | declare sub remove ()
49 | declare function is_empty () as integer
50 | declare function is_singular () as integer
51 | declare function get_next () as Listtype(T_) ptr
52 | declare function get_prev () as Listtype(T_) ptr
53 | declare function get_owner () as Listtype_p_##T_
54 | end type
55 | #endmacro
56 |
57 | #macro DEFINE_LIST(T_)
58 | constructor Listtype(T_) (offset as uinteger)
59 | assert(offset <> 0)
60 |
61 | this.next_ptr = @this
62 | this.prev_ptr = @this
63 | #if defined(Listtype_r_##t_)
64 | this.owner = Listtype_p_##T_(cast(T_ ptr, cast(any ptr, @this)-offset))
65 | #else
66 | this.owner = cast(Listtype_p_##T_, cast(any ptr, @this)-offset)
67 | #endif
68 | end constructor
69 |
70 | constructor Listtype(T_) ()
71 | this.next_ptr = @this
72 | this.prev_ptr = @this
73 | #if not defined(Listtype_r_##t_)
74 | this.owner = 0
75 | #endif
76 | end constructor
77 |
78 | destructor Listtype(T_)
79 | this.remove()
80 | end destructor
81 |
82 | sub Listtype(T_).insert_after (new_head as Listtype(T_) ptr)
83 | new_head->next_ptr = this.next_ptr
84 | new_head->prev_ptr = @this
85 |
86 | this.next_ptr->prev_ptr = new_head
87 | this.next_ptr = new_head
88 | end sub
89 |
90 | sub Listtype(T_).insert_before (new_head as Listtype(T_) ptr)
91 | new_head->prev_ptr = this.prev_ptr
92 | new_head->next_ptr = @this
93 |
94 | this.prev_ptr->next_ptr = new_head
95 | this.prev_ptr = new_head
96 | end sub
97 |
98 | sub Listtype(T_).remove ()
99 | this.prev_ptr->next_ptr = this.next_ptr
100 | this.next_ptr->prev_ptr = this.prev_ptr
101 | end sub
102 |
103 | function Listtype(T_).is_empty () as integer
104 | return (this.next_ptr = @this)
105 | end function
106 |
107 | function Listtype(T_).is_singular () as integer
108 | if (not this.is_empty()) then
109 | return (this.next_ptr = this.prev_ptr)
110 | end if
111 |
112 | return 0
113 | end function
114 |
115 | function Listtype(T_).get_next () as Listtype(T_) ptr
116 | return this.next_ptr
117 | end function
118 |
119 | function Listtype(T_).get_prev () as Listtype(T_) ptr
120 | return this.prev_ptr
121 | end function
122 |
123 | function Listtype(T_).get_owner () as Listtype_p_##T_
124 | return this.owner
125 | end function
126 | #endmacro
127 |
128 |
129 | #macro list_foreach (ITERATOR_, LIST_)
130 | scope
131 | dim ITERATOR_ as typeof(LIST_) ptr = LIST_.get_next()
132 | while (ITERATOR_ <> @LIST_)
133 |
134 | #endmacro
135 |
136 | #define list_foreach_exit exit while
137 |
138 | #macro list_next (ITERATOR_)
139 | ITERATOR_ = ITERATOR_->get_next()
140 | wend
141 | end scope
142 | #endmacro
143 |
--------------------------------------------------------------------------------
/kernel/src/lapic.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "apic.bi"
20 | #include "debug.bi"
21 | #include "cpu.bi"
22 | #include "vmm.bi"
23 | #include "pmm.bi"
24 | #include "pic.bi"
25 | #include "panic.bi"
26 |
27 | dim apic_enabled as boolean = false
28 |
29 | const LOCAL_APIC_BASE_MSR = &h1B
30 | const LOCAL_APIC_BASE_ADDR_MASK = &hFFFFFF000
31 |
32 | const LOCAL_APIC_REG_ID = &h0020 '' (RW)
33 | const LOCAL_APIC_REG_VERSION = &h0030 '' (R)
34 | const LOCAL_APIC_REG_TASK_PRIO = &h0080 '' (RW)
35 | const LOCAL_APIC_REG_ARBIT_PRIO = &h0090 '' (R)
36 | const LOCAL_APIC_REG_PROC_PRIO = &h00A0 '' (R)
37 | const LOCAL_APIC_REG_EOI = &h00B0 '' (W)
38 | const LOCAL_APIC_REG_REMOTE_READ = &h00C0 '' (R)
39 | const LOCAL_APIC_REG_LOGICAL_DEST = &h00D0 '' (RW)
40 | const LOCAL_APIC_REG_DEST_FORMAT = &h00E0 '' (RW)
41 | const LOCAL_APIC_REG_SPIV = &h00F0 '' (RW)
42 | const LOCAL_APIC_REG_ERROR_STATUS = &h0280 '' (R)
43 | const LOCAL_APIC_REG_LVT_CMCI = &h02F0 '' (RW)
44 | const LOCAL_APIC_REG_ICR_LOW = &h0300 '' (RW)
45 | const LOCAL_APIC_REG_ICR_HIGH = &h0310 '' (RW)
46 | const LOCAL_APIC_REG_LVT_TIMER = &h0320 '' (RW)
47 | const LOCAL_APIC_REG_LVT_THERM = &h0330 '' (RW)
48 | const LOCAL_APIC_REG_LVT_PERFMON = &h0340 '' (RW)
49 | const LOCAL_APIC_REG_LVT_LINT0 = &h0350 '' (RW)
50 | const LOCAL_APIC_REG_LVT_LINT1 = &h0360 '' (RW)
51 | const LOCAL_APIC_REG_LVT_ERROR = &h0370 '' (RW)
52 | const LOCAL_APIC_REG_TIMER_INITCNT = &h0380 '' (RW)
53 | const LOCAL_APIC_REG_TIMER_CURRCNT = &h0390 '' (R)
54 | const LOCAL_APIC_REG_TIMER_DIV = &h03E0 '' (RW)
55 |
56 | const LOCAL_APIC_SPIV_SOFT_ENABLE = &h100
57 |
58 | dim shared lapic_base_virt as uinteger = 0
59 |
60 | sub lapic_write_register (register_offset as uinteger, value as uinteger)
61 | *(cast(uinteger ptr, lapic_base_virt+register_offset)) = value
62 | end sub
63 |
64 | function lapic_read_register (register_offset as uinteger) as uinteger
65 | return *(cast(uinteger ptr, lapic_base_virt+register_offset))
66 | end function
67 |
68 | '' TODO: set spurious interrupt vector
69 | '' FIXME: split up into "once"- and "per-cpu"-parts
70 | sub lapic_init ()
71 | pic_mask_all()
72 |
73 | dim lapic_base_phys as uinteger = cuint(read_msr(LOCAL_APIC_BASE_MSR) and LOCAL_APIC_BASE_ADDR_MASK)
74 | write_msr(LOCAL_APIC_BASE_MSR, read_msr(LOCAL_APIC_BASE_MSR))
75 |
76 | printk(LOG_DEBUG COLOR_GREEN "LAPIC: " COLOR_RESET !"base addr: %X\n", cuint(read_msr(LOCAL_APIC_BASE_MSR) and LOCAL_APIC_BASE_ADDR_MASK))
77 |
78 | lapic_base_virt = cuint(vmm_kernel_automap(cast(any ptr, lapic_base_phys), PAGE_SIZE, VMM_FLAGS.KERNEL_DATA or VMM_PTE_FLAGS.NOT_CACHEABLE))
79 |
80 | '' set the APIC Software Enable/Disable flag in the Spurious-Interrupt Vector Register
81 | '' FIXME: properly initialize the SPI vector. See manual 10.9, and http://forum.osdev.org/viewtopic.php?p=83547&sid=eb062848679db0c0532f4b97b949d104#p83547
82 | lapic_write_register(LOCAL_APIC_REG_SPIV, lapic_read_register(LOCAL_APIC_REG_SPIV) or LOCAL_APIC_SPIV_SOFT_ENABLE)
83 |
84 | apic_enabled = true
85 | end sub
86 |
87 | sub lapic_eoi ()
88 | assert(apic_enabled = true)
89 |
90 | '' writing to the EOI register signals completion of the handler routine
91 | lapic_write_register(LOCAL_APIC_REG_EOI, 0)
92 | end sub
93 |
94 | '' FIXME: magic values are bad.
95 | '' FIXME: this currently always start the CPU with the local-APIC-ID 1, and
96 | '' the delay-loop is lousy.
97 | sub lapic_startup_ipi (trampoline_addr as any ptr)
98 | assert(apic_enabled = true)
99 |
100 | lapic_write_register(LOCAL_APIC_REG_ICR_HIGH, 1 shl 24)
101 | lapic_write_register(LOCAL_APIC_REG_ICR_LOW, (5 shl 8) or (1 shl 14))
102 |
103 | for i as integer = 0 to &h0FFFFF
104 |
105 | next
106 |
107 | lapic_write_register(LOCAL_APIC_REG_ICR_HIGH, 1 shl 24)
108 | lapic_write_register(LOCAL_APIC_REG_ICR_LOW, (((cuint(trampoline_addr) \ &h1000) and &hFF) or (6 shl 8) or (1 shl 14)))
109 | end sub
110 |
--------------------------------------------------------------------------------
/kernel/src/arch/x86/gdt.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "kernel.bi"
20 | #include "gdt.bi"
21 | #include "video.bi"
22 |
23 | type gdtr_type field=1
24 | limit as ushort
25 | start as uinteger
26 | end type
27 |
28 | type gdt_type field=1
29 | limit_low as ushort
30 | start_low as ushort
31 | start_middle as ubyte
32 | accessbyte as ubyte
33 | flags_limit2 as ubyte
34 | start_high as ubyte
35 | end type
36 |
37 | '' flags for the access-byte
38 | const FLAG_PRESENT as ubyte = &h80 '' must be set for an active entry
39 | const FLAG_PRIVILEGE_RING_3 as ubyte = &h60
40 | const FLAG_PRIVILEGE_RING_2 as ubyte = &h40
41 | const FLAG_PRIVILEGE_RING_1 as ubyte = &h20
42 | const FLAG_PRIVILEGE_RING_0 as ubyte = &h00
43 | const FLAG_SEGMENT as ubyte = &h10 '' set for Code-/Data-segments, unset for gates and TSS
44 | const FLAG_EXECUTABLE as ubyte = &h08 '' unset = DS, set = CS
45 | const FLAG_DC as ubyte = &h04
46 | const FLAG_RW as ubyte = &h02 '' CS: read access, DS: write access
47 | const FLAG_ACCESSED as ubyte = &h01 '' set by CPU. DO NOT USE!
48 | const FLAG_TSS as ubyte = &h09 '' tss is a bit special
49 |
50 | '' flags for the flags-byte
51 | const FLAG_GRANULARITY as ubyte = &h08 '' if set, size is in 4KB units
52 | const FLAG_SIZE as ubyte = &h04 '' unset = 16 bit PM, set = 32 bit PM
53 | const FLAG_LONG_MODE as ubyte = &h02 '' if set, it's a long mode segment
54 | const FLAG_AVAILABLE as ubyte = &h01 '' free bit
55 |
56 | const TABLE_SIZE = 5
57 |
58 | declare sub gdt_set_entry (i as ushort, start as uinteger, limit as uinteger, access as ubyte, flags as ubyte)
59 |
60 | dim shared gdtr as gdtr_type
61 | dim shared gdt (0 to TABLE_SIZE) as gdt_type
62 | dim shared tss as task_state_segment
63 |
64 |
65 | '' this sub initializes the GDT with Code- and Data-Segments for Ring 0 and Ring 3.
66 | '' it also does basic tss-setup
67 | sub gdt_prepare ()
68 | tss_ptr = @tss '' initialize the tss-pointer (used in other parts of the kernel)
69 | tss.ss0 = &h10 '' set the kernel stack segment of the tss
70 | tss.io_bitmap_offset = TSS_IO_BITMAP_NOT_LOADED
71 |
72 | '' RING-0 Code-Segment
73 | gdt_set_entry(1, 0, &hFFFFF, (FLAG_PRESENT or FLAG_PRIVILEGE_RING_0 or FLAG_SEGMENT or FLAG_EXECUTABLE or FLAG_RW), (FLAG_GRANULARITY or FLAG_SIZE))
74 |
75 | '' RING-0 Data-Segment
76 | gdt_set_entry(2, 0, &hFFFFF, (FLAG_PRESENT or FLAG_PRIVILEGE_RING_0 or FLAG_SEGMENT or FLAG_RW), (FLAG_GRANULARITY or FLAG_SIZE))
77 |
78 | '' RING-3 Code-Segment
79 | gdt_set_entry(3, 0, &hFFFFF, (FLAG_PRESENT or FLAG_PRIVILEGE_RING_3 or FLAG_SEGMENT or FLAG_EXECUTABLE or FLAG_RW), (FLAG_GRANULARITY or FLAG_SIZE))
80 |
81 | '' RING-3 Data-Segment
82 | gdt_set_entry(4, 0, &hFFFFF, (FLAG_PRESENT or FLAG_PRIVILEGE_RING_3 or FLAG_SEGMENT or FLAG_RW), (FLAG_GRANULARITY or FLAG_SIZE))
83 |
84 | '' TSS
85 | gdt_set_entry(5, cuint(tss_ptr), sizeof(task_state_segment), (FLAG_PRESENT or FLAG_PRIVILEGE_RING_3 or FLAG_TSS), 0)
86 |
87 | gdtr.limit = (TABLE_SIZE+1)*8-1 '' calculate the size of the entries + null-entry
88 | gdtr.start = cuint(@gdt(0)) '' set the address of the table
89 | end sub
90 |
91 | sub gdt_load ()
92 | '' load the gdt
93 | asm lgdt [gdtr]
94 |
95 | '' refresh the segment registers, so the gdt is really being used
96 | asm
97 | mov ax, &h10
98 | mov ds, ax
99 | mov es, ax
100 | mov fs, ax
101 | mov gs, ax
102 | mov ss, ax
103 | ljmp &h08:gdt_jmp
104 | gdt_jmp:
105 | end asm
106 |
107 | '' load the task-register
108 | asm
109 | mov ax, &h28
110 | ltr ax
111 | end asm
112 | end sub
113 |
114 | '' this sub is just a helper function to provide easier access to the GDT.
115 | '' it puts the passed arguments in the right place of a GDT-entry.
116 | sub gdt_set_entry (index as ushort, start as uinteger, limit as uinteger, accessbyte as ubyte, flags as ubyte)
117 | gdt(index).limit_low = loword(limit)
118 | gdt(index).start_low = loword(start)
119 | gdt(index).start_middle = lobyte(hiword(start))
120 | gdt(index).accessbyte = accessbyte
121 | gdt(index).flags_limit2 = (lobyte(hiword(limit)) and &h0F)
122 | gdt(index).flags_limit2 or= ((flags shl 4) and &hF0)
123 | gdt(index).start_high = hibyte(hiword(start))
124 | end sub
125 |
--------------------------------------------------------------------------------
/kernel/src/interrupt_handler.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2016 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "kernel.bi"
20 | #include "interrupt_handler.bi"
21 | #include "isf.bi"
22 | #include "thread.bi"
23 | #include "interrupt.bi"
24 | #include "apic.bi"
25 | #include "process.bi"
26 | #include "syscall.bi"
27 | #include "panic.bi"
28 | #include "pmm.bi"
29 | #include "kmm.bi"
30 |
31 | DECLARE_LIST(irq_handler_type)
32 | DEFINE_LIST(irq_handler_type)
33 |
34 | type irq_handler_type
35 | process as process_type ptr
36 | handler as any ptr
37 |
38 | list as Listtype(irq_handler_type) = Listtype(irq_handler_type)(offsetof(irq_handler_type, list))
39 |
40 | declare operator new (size as uinteger) as any ptr
41 | declare operator new[] (size as uinteger) as any ptr
42 | declare operator delete (buffer as any ptr)
43 |
44 | declare constructor (process as process_type ptr, handler as any ptr)
45 | end type
46 |
47 | operator irq_handler_type.new (size as uinteger) as any ptr
48 | return kmalloc(size)
49 | '' constructor is called automatically
50 | end operator
51 |
52 | operator irq_handler_type.delete (buffer as any ptr)
53 | kfree(buffer)
54 | '' destructor is called automatically
55 | end operator
56 |
57 | constructor irq_handler_type (process as process_type ptr, handler as any ptr)
58 | this.process = process
59 | this.handler = handler
60 | end constructor
61 |
62 | dim shared irq_handlers(0 to 15) as Listtype(irq_handler_type)
63 |
64 | function register_irq_handler (process as process_type ptr, irq as integer, handler_address as any ptr) as boolean
65 | if ((irq < lbound(irq_handlers,1)) or (irq > ubound(irq_handlers,1))) then return false
66 |
67 | dim h as irq_handler_type ptr = new irq_handler_type(process, handler_address)
68 | irq_handlers(irq).insert_after(@h->list)
69 |
70 | '' FIXME: hardcoding the x86 IRQ-offset? naaaaaaah....
71 | interrupt_unmask(irq+&h20)
72 | return true
73 | end function
74 |
75 | '' this is the common interrupt handler which gets called for every interrupt.
76 | function handle_interrupt cdecl (isf as interrupt_stack_frame ptr) as interrupt_stack_frame ptr
77 | dim reschedule as uinteger = false
78 |
79 | select case isf->int_nr
80 | case 0 to &h0C '' exception
81 | panic_exception(isf) '' show panic screen
82 |
83 | case &h0D
84 | if (tss_ptr->io_bitmap_offset = TSS_IO_BITMAP_NOT_LOADED) then
85 | set_io_bitmap()
86 | else
87 | panic_exception(isf)
88 | end if
89 |
90 | case &h0E to &h13
91 | panic_exception(isf)
92 |
93 | case &h21 to &h2F
94 | '' spurious IRQ?
95 | if (interrupt_is_spurious(isf->int_nr)) then
96 | '' takes care of spurious interrupts and sends EOI if needed
97 | interrupt_eoi(isf->int_nr)
98 | return isf
99 | end if
100 |
101 | '' mask the IRQ to prevent it from firing again (gets unmasked when the thread is done)
102 | '' even when no popup-thread was created we mask to prevent IRQ-storms
103 | interrupt_mask(isf->int_nr)
104 |
105 | '' IRQ
106 | list_foreach(h, irq_handlers(isf->int_nr-&h20))
107 | dim x as irq_handler_type ptr = h->get_owner()
108 | dim thread as thread_type ptr = new thread_type(x->process, x->handler, 1, THREAD_FLAG_POPUP)
109 |
110 | dim stack_p as any ptr = vmm_resolve(@(thread->parent_process->context), thread->stack_area->address + (thread->stack_area->pages-1)*PAGE_SIZE)
111 | dim m as uinteger ptr = vmm_kernel_automap(cast(any ptr, stack_p), PAGE_SIZE)
112 | m[PAGE_SIZE\4-1] = isf->int_nr-&h20
113 | m[PAGE_SIZE\4-2] = 0 '' return address, needed because of cdecl!
114 | vmm_kernel_unmap(m, PAGE_SIZE)
115 | thread->isf->esp -= 8
116 |
117 | thread->activate()
118 | list_next(h)
119 |
120 | case &h20 '' timer IRQ
121 | reschedule = true
122 |
123 | case &hFF '' syscall interrupt
124 | isf->eax = syscall_handler(isf->eax, isf->ebx, isf->esi, isf->edi)
125 |
126 | case else
127 |
128 | end select
129 |
130 | if (get_current_thread() <> nullptr) then
131 | if (get_current_thread()->flags and THREAD_FLAG_RESCHEDULE) then
132 | reschedule = true
133 | get_current_thread()->flags and= not THREAD_FLAG_RESCHEDULE
134 | end if
135 | end if
136 |
137 | if (reschedule) then
138 | thread_switch(isf)
139 | end if
140 |
141 | '' important: send EOI if necessary
142 | interrupt_eoi(isf->int_nr)
143 |
144 | return get_current_thread()->isf
145 | end function
146 |
--------------------------------------------------------------------------------
/kernel/src/panic.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "panic.bi"
20 | #include "isf.bi"
21 | #include "video.bi"
22 |
23 | sub panic_set_clear_on_panic (b as boolean)
24 | panic_clear_on_panic = b
25 | end sub
26 |
27 | sub panic_hlt ()
28 | printk(LOG_ERR COLOR_RED !"\nSYSTEM HALTED")
29 | cpu_halt()
30 | end sub
31 |
32 | sub panic_exception (isf as interrupt_stack_frame ptr)
33 | cpu_disable_interrupts()
34 | if (panic_clear_on_panic) then video_clean()
35 | printk(LOG_ERR COLOR_RED !"\n--------------------------------------------------------------------------------")
36 | printk(LOG_ERR !"\nKERNEL PANIC\n")
37 |
38 | select case (isf->int_nr)
39 | case &h00
40 | printk(LOG_ERR !"EXCEPTION 0x00 - Division by Zero (#DE)\n")
41 | case &h01
42 | printk(LOG_ERR !"EXCEPTION 0x01 - Debug (#DB)\n")
43 | case &h02
44 | printk(LOG_ERR !"EXCEPTION 0x02 - Non-maskable Interrupt (#NMI)\n")
45 | case &h03
46 | printk(LOG_ERR !"EXCEPTION 0x03 - Breakpoint (#BP)\n")
47 | case &h04
48 | printk(LOG_ERR !"EXCEPTION 0x04 - Overflow (#OF)\n")
49 | case &h05
50 | printk(LOG_ERR !"EXCEPTION 0x05 - Bound Range Exceeded (#BR)\n")
51 | case &h06
52 | printk(LOG_ERR !"EXCEPTION 0x06 - Invalid Opcode (#UD)\n")
53 | case &h07
54 | printk(LOG_ERR !"EXCEPTION 0x07 - Device Not Available (#NM)\n")
55 | case &h08
56 | printk(LOG_ERR !"EXCEPTION 0x08 - Double Fault (#DF)\n")
57 | case &h09
58 | printk(LOG_ERR !"EXCEPTION 0x09 - Coprocessor Segment Overrun\n")
59 | case &h0A
60 | printk(LOG_ERR !"EXCEPTION 0x0A - Invalid TSS (#TS)\n")
61 | case &h0B
62 | printk(LOG_ERR !"EXCEPTION 0x0B - Segment Not Present (#NP)\n")
63 | case &h0C
64 | printk(LOG_ERR !"EXCEPTION 0x0C - Stack-Segment Fault (#SS)\n")
65 | case &h0D
66 | printk(LOG_ERR !"EXCEPTION 0x0D - General Protection Fault (#GP)\n")
67 | case &h0E
68 | printk(LOG_ERR !"EXCEPTION 0x0E - Page Fault (#PF)\n")
69 | printk(LOG_ERR COLOR_RED !" - page active : ")
70 | if (isf->errorcode and &h01) then
71 | printk(LOG_ERR COLOR_RESET !"yes\n")
72 | else
73 | printk(LOG_ERR COLOR_RESET !"no\n")
74 | end if
75 | printk(LOG_ERR COLOR_RED !" - access type : ")
76 | if (isf->errorcode and &h02) then
77 | printk(LOG_ERR COLOR_RESET !"write\n")
78 | else
79 | printk(LOG_ERR COLOR_RESET !"read\n")
80 | end if
81 | printk(LOG_ERR COLOR_RED !" - rights : ")
82 | if (isf->errorcode and &h04) then
83 | printk(LOG_ERR COLOR_RESET !"user\n")
84 | else
85 | printk(LOG_ERR COLOR_RESET !"kernel\n")
86 | end if
87 | printk(LOG_ERR COLOR_RED !" - reserved : ")
88 | if (isf->errorcode and &h08) then
89 | printk(LOG_ERR COLOR_RESET !"yes\n")
90 | else
91 | printk(LOG_ERR COLOR_RESET !"no\n")
92 | end if
93 | printk(LOG_ERR COLOR_RED !" - access target: ")
94 | if (isf->errorcode and &h10) then
95 | printk(LOG_ERR COLOR_RESET !"code\n")
96 | else
97 | printk(LOG_ERR COLOR_RESET !"data\n")
98 | end if
99 | case &h0F
100 | printk(LOG_ERR !"EXCEPTION 0x0F - RESERVED\n")
101 | case &h10
102 | printk(LOG_ERR !"EXCEPTION 0x10 - x87 Floating Point (#MF)\n")
103 | case &h11
104 | printk(LOG_ERR !"EXCEPTION 0x11 - Alignment Check (#AC)\n")
105 | case &h12
106 | printk(LOG_ERR !"EXCEPTION 0x12 - Machine Check (#MC)\n")
107 | case &h13
108 | printk(LOG_ERR !"EXCEPTION 0x13 - SIMD Floating Point (#XM/#XF)\n")
109 | case &h14 to &h1F
110 | printk(LOG_ERR !"EXCEPTION - RESERVED EXCEPTION\n")
111 | end select
112 |
113 | printk(LOG_ERR !"\n")
114 | printk(LOG_ERR COLOR_RED "error: " COLOR_RESET !"0x%08X\n", isf->errorcode)
115 |
116 | dim as uinteger t_cr0, t_cr2, t_cr3
117 |
118 | asm
119 | mov eax, cr0
120 | mov [t_cr0], eax
121 | mov eax, cr2
122 | mov [t_cr2], eax
123 | mov eax, cr3
124 | mov [t_cr3], eax
125 | end asm
126 | printk(LOG_ERR COLOR_RED "cr0: " COLOR_RESET "0x%08X" COLOR_RED ", cr2: " COLOR_RESET "0x%08X" COLOR_RED ", cr3: " COLOR_RESET !"0x%08X\n", t_cr0, t_cr2, t_cr3)
127 | printk(LOG_ERR COLOR_RED "eax: " COLOR_RESET "0x%08X" COLOR_RED ", ebx: " COLOR_RESET "0x%08X" COLOR_RED ", ecx: " COLOR_RESET "0x%08X" COLOR_RED ", edx: " COLOR_RESET !"0x%08X\n", isf->eax, isf->ebx, isf->ecx, isf->edx)
128 | printk(LOG_ERR COLOR_RED "ebp: " COLOR_RESET "0x%08X" COLOR_RED ", esp: " COLOR_RESET "0x%08X" COLOR_RED ", esi: " COLOR_RESET "0x%08X" COLOR_RED ", edi: " COLOR_RESET !"0x%08X\n", isf->ebp, isf->esp, isf->esi, isf->edi)
129 | printk(LOG_ERR COLOR_RED "eip: " COLOR_RESET "0x%08X" COLOR_RED ", ss: " COLOR_RESET "0x%04X" COLOR_RED ", cs: " COLOR_RESET "0x%04X" COLOR_RED ", eflags: " COLOR_RESET !"0x%08X\n", isf->eip, isf->ss, isf->cs, isf->eflags)
130 |
131 | ' maybe print some other registers here
132 | panic_hlt()
133 | end sub
134 |
--------------------------------------------------------------------------------
/kernel/src/vfs.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "vfs.bi"
20 | #include "kernel.bi"
21 | #include "string_tokenizer.bi"
22 | #include "zstring.bi"
23 | #include "video.bi"
24 | #include "process.bi"
25 |
26 | DEFINE_LIST(vfs_node)
27 | DEFINE_REFCOUNTPTR(vfs_node)
28 |
29 | dim shared vfs_root as RefCountPtr(vfs_node)
30 | dim shared fd_id_generator as uid128_generator
31 |
32 | sub vfs_init ()
33 | vfs_root = new vfs_node("vfs_root", nullptr, VFS_FLAGS_KERNEL_NODE)
34 |
35 | var one = new vfs_node("vfs_1", vfs_root.ref, VFS_FLAGS_KERNEL_NODE)
36 | var two = new vfs_node("vfs_2", vfs_root.ref, VFS_FLAGS_KERNEL_NODE)
37 | var three = new vfs_node("vfs_3", vfs_root.ref, VFS_FLAGS_KERNEL_NODE)
38 |
39 | var testnode = new vfs_node("testnode", two, VFS_FLAGS_KERNEL_NODE)
40 |
41 | var t = vfs_parse_path("/vfs_2/testnode")
42 | printk(LOG_DEBUG !"node name: %s\n", t->name)
43 | end sub
44 |
45 | function vfs_get_root as RefCountPtr(vfs_node)
46 | return vfs_root
47 | end function
48 |
49 | operator vfs_node.new (size as uinteger) as any ptr
50 | return kmalloc(size)
51 | end operator
52 |
53 | operator vfs_node.delete (buffer as any ptr)
54 | kfree(buffer)
55 | end operator
56 |
57 | constructor vfs_node (name as zstring ptr, parent as vfs_node ptr, flags as integer, owner as process_type ptr = nullptr)
58 | '' TODO: don't rely on userspace string pointers, copy instead
59 | this.name = name
60 | this.parent = parent
61 | this.flags = flags
62 | this.owner = owner
63 |
64 | if (parent <> nullptr) then
65 | '' TODO: maybe keep the list sorted somehow?
66 | parent->child_list.insert_after(@this.node_list)
67 | end if
68 | end constructor
69 |
70 | function vfs_node.getChildByName (name as zstring) as RefCountPtr(vfs_node)
71 | '' loop through all child nodes, search for the one with the right name
72 | list_foreach(child, this.child_list)
73 | dim child_node as RefCountPtr(vfs_node) = child->get_owner()
74 |
75 | if (zstring_cmp(name, *child_node->name) = 0) then
76 | return child_node
77 | end if
78 | list_next(child)
79 |
80 | return nullptr
81 | end function
82 |
83 | DEFINE_LIST(vfs_fd)
84 |
85 | operator vfs_fd.new (size as uinteger) as any ptr
86 | return kmalloc(size)
87 | end operator
88 |
89 | operator vfs_fd.delete (buffer as any ptr)
90 | kfree(buffer)
91 | end operator
92 |
93 | constructor vfs_fd (process as process_type ptr, node as RefCountPtr(vfs_node))
94 | this.id = fd_id_generator.generate()
95 | this.node = node
96 |
97 | '' add ourself to a list of descriptors for this process
98 | process->file_descriptors.insert_after(@this.fd_list)
99 | end constructor
100 |
101 | function vfs_parse_path (path as zstring) as RefCountPtr(vfs_node)
102 | if (path[0] = asc("/")) then
103 | dim cur_node as RefCountPtr(vfs_node) = vfs_root
104 | dim st as StringTokenizer = StringTokenizer(@path)
105 | do
106 | dim x as zstring ptr = st.getToken(strptr("/"))
107 | if (x = 0) then exit do
108 |
109 | cur_node = cur_node->getChildByName(*x)
110 |
111 | if (cur_node.ref = nullptr) then exit do
112 | loop
113 |
114 | return cur_node
115 | end if
116 |
117 | return RefCountPtr(vfs_node)
118 | end function
119 |
120 | function vfs_parse_path_afap (path as zstring) as RefCountPtr(vfs_node)
121 | if (path[0] = asc("/")) then
122 | dim cur_node as RefCountPtr(vfs_node) = vfs_root
123 | dim st as StringTokenizer = StringTokenizer(@path)
124 | do
125 | dim x as zstring ptr = st.getToken(strptr("/"))
126 | if (x = 0) then exit do
127 |
128 | dim next_node as RefCountPtr(vfs_node) = cur_node->getChildByName(*x)
129 | if (next_node.ref = nullptr) then exit do
130 | cur_node = next_node
131 | loop
132 |
133 | return cur_node
134 | end if
135 |
136 | return RefCountPtr(vfs_node)
137 | end function
138 |
139 | function vfs_create (path as zstring ptr, name_ as zstring ptr, owner as process_type ptr) as RefCountPtr(vfs_node)
140 | '' the path must be cached in the VFS - we don't support arbitrary paths at the moment (should we ever?)
141 |
142 | '' parse the path to get the parent-node
143 | dim parent_node as RefCountPtr(vfs_node) = vfs_parse_path(*path)
144 | if (parent_node.get_count() = 0) then return nullptr
145 |
146 | '' create, register & return the new node
147 | dim new_node as RefCountPtr(vfs_node) = new vfs_node(name_, parent_node.ref, 0, owner)
148 | return new_node
149 | end function
150 |
151 | function vfs_open (thread as thread_type ptr, path as zstring ptr, flags as uinteger) as vfs_fd ptr
152 | '' TODO: what about permissions?
153 | '' TODO: error-signaling is very unprecise
154 |
155 | '' parse the path and get the node
156 | dim node as RefCountPtr(vfs_node) = vfs_parse_path(*path)
157 | if (node.get_count() = 0) then return nullptr
158 |
159 | '' create a new file-descriptor
160 | dim fd as vfs_fd ptr = new vfs_fd(thread->parent_process, node)
161 | return fd
162 | end function
163 |
--------------------------------------------------------------------------------
/kernel/src/main.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "multiboot.bi"
20 | #include "gdt.bi"
21 | #include "idt.bi"
22 | #include "acpi.bi"
23 | #include "apic.bi"
24 | #include "interrupt.bi"
25 | #include "pit.bi"
26 | #include "pmm.bi"
27 | #include "vmm.bi"
28 | #include "kmm.bi"
29 | #include "mem.bi"
30 | #include "process.bi"
31 | #include "modules.bi"
32 | #include "debug.bi"
33 | #include "panic.bi"
34 | #include "video.bi"
35 | #include "zstring.bi"
36 | #include "cpu.bi"
37 | #include "smp.bi"
38 | #include "io_man.bi"
39 | #include "vfs.bi"
40 |
41 | sub parse_cmdline (cmd_string as zstring ptr)
42 | if (zstring_instr(*cmd_string, "-verbose") > 0) then
43 | debug_set_loglevel(0) '' show every log-message
44 | else
45 | debug_set_loglevel(2) '' show only critical messages
46 | end if
47 |
48 | if (zstring_instr(*cmd_string, "-no-clear-on-panic") > 0) then
49 | panic_set_clear_on_panic(false)
50 | else
51 | panic_set_clear_on_panic(true)
52 | end if
53 |
54 | #if defined (FROST_DEBUG)
55 | if (zstring_instr(*cmd_string, "-serial-debugging") > 0) then
56 | debug_serial_init()
57 |
58 | if (zstring_instr(*cmd_string, "-serial-colorized") > 0) then
59 | video_serial_set_colorized(true)
60 | end if
61 | end if
62 | #endif
63 | end sub
64 |
65 | '' TODO: move this to some better place
66 | declare sub sysenter_entry ()
67 |
68 | '' this sub really is the main function of the kernel.
69 | '' it is called by start.asm after setting up the stack.
70 | sub main (magicnumber as multiboot_uint32_t, t_mbinfo as multiboot_info ptr)
71 | '' we copy the mbinfo structure so it gets automatically mapped with the kernel
72 | dim mb_info as multiboot_info
73 | memcpy(@mb_info, t_mbinfo, sizeof(multiboot_info))
74 |
75 | video_clean()
76 | video_hide_cursor()
77 |
78 | if (mb_info.flags and MULTIBOOT_INFO_CMDLINE) then
79 | parse_cmdline(cast(zstring ptr, mb_info.cmdline))
80 | end if
81 |
82 | printk(LOG_INFO COLOR_BLUE !"FROST (%s)\n" COLOR_RESET, FROST_VERSION)
83 | printk(LOG_INFO COLOR_GREEN "bootloader: " COLOR_RESET !"%s\n", cast(zstring ptr, mb_info.boot_loader_name))
84 | printk(LOG_INFO COLOR_GREEN "cmdline: " COLOR_RESET !"%s\n", cast(zstring ptr, mb_info.cmdline))
85 |
86 | scope
87 | dim zstr as zstring*13
88 | cpu_get_vendor(@zstr)
89 | printk(LOG_INFO !"CPU vendor: %s\n", @zstr)
90 | end scope
91 |
92 | gdt_prepare()
93 | gdt_load()
94 | idt_prepare()
95 | idt_load()
96 |
97 | pit_set_frequency(100)
98 |
99 | acpi_init()
100 |
101 | '' two-step initialization of the PMM
102 | '' (the normal-allocator needs paging)
103 | pmm_init(@mb_info, PMM_ZONE_DMA24)
104 | printk(LOG_INFO COLOR_GREEN "PMM: " COLOR_RESET !"DMA24 zone initialized\n")
105 | vmm_init()
106 | pmm_init(@mb_info, PMM_ZONE_NORMAL)
107 | printk(LOG_INFO COLOR_GREEN "PMM: " COLOR_RESET !"normal zone initialized\n")
108 | printk(LOG_INFO COLOR_GREEN "PMM: " COLOR_RESET !"total RAM: %uMiB, free RAM: %uMiB\n", cuint(pmm_get_total()\1048576), cuint(pmm_get_free()\1048576))
109 | vmm_init_local()
110 | printk(LOG_INFO COLOR_GREEN "VMM: " COLOR_RESET !"paging initialized\n")
111 |
112 | interrupt_init()
113 |
114 | printk(LOG_INFO COLOR_GREEN "KMM: " COLOR_RESET !"initializing heap\n")
115 |
116 | '' initialize the heap:
117 | '' starts at 256MB
118 | '' initial size 1MB
119 | '' minimum size 1MB
120 | '' maximum size 256MB
121 | kmm_init(&h10000000, &h10100000, &h100000, &h10000000)
122 | printk(LOG_INFO COLOR_GREEN "KMM: " COLOR_RESET !"heap initialized\n")
123 |
124 | if (cpu_has_local_apic()) then
125 | printk(LOG_INFO COLOR_GREEN "LAPIC: " COLOR_RESET !"CPU has local APIC\n")
126 | 'lapic_init()
127 | '' ioapic_init()
128 | end if
129 |
130 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"initializing\n")
131 | 'smp_init()
132 |
133 | printk(LOG_INFO COLOR_GREEN "VFS: " COLOR_RESET !"initializing...\n")
134 | vfs_init()
135 |
136 | init_ports()
137 |
138 | printk(LOG_INFO !"loading init module...")
139 | load_init_module(@mb_info)
140 | printk(LOG_INFO !"done.\n")
141 |
142 | printk(LOG_INFO !"loading modules...")
143 | load_modules(@mb_info)
144 | printk(LOG_INFO !"done.\n")
145 |
146 | '' TODO: We should only set up SYSENTER if the CPU supports it
147 | write_msr(MSR_IA32_SYSENTER_CS, &h0008)
148 | write_msr(MSR_IA32_SYSENTER_EIP, cuint(@sysenter_entry))
149 |
150 | thread_create_idle_thread()
151 | interrupt_unmask(&h20)
152 |
153 | '' the scheduler takes over here
154 | asm sti
155 | do : loop
156 | end sub
157 |
158 | extern start_ctors alias "start_ctors" as byte
159 | extern end_ctors alias "end_ctors" as byte
160 | extern start_dtors alias "start_dtors" as byte
161 | extern end_dtors alias "end_dtors" as byte
162 |
163 | sub kinit ()
164 | dim ctor as uinteger ptr = cast(uinteger ptr, @start_ctors)
165 |
166 | while ctor < @end_ctors
167 | dim ictor as sub () = cast(sub(), *ctor)
168 | ictor()
169 |
170 | ctor += 1
171 | wend
172 | end sub
173 |
--------------------------------------------------------------------------------
/kernel/src/pmm.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "pmm.bi"
20 | #include "vmm.bi"
21 | #include "mem.bi"
22 | #include "kernel.bi"
23 | #include "multiboot.bi"
24 | #include "spinlock.bi"
25 | #include "panic.bi"
26 |
27 | '' the amount of free memory
28 | dim shared free_mem as uinteger = 0
29 | dim shared total_mem as uinteger = 0
30 |
31 | function pmm_get_total () as uinteger
32 | return total_mem
33 | end function
34 |
35 | function pmm_get_free () as uinteger
36 | return free_mem
37 | end function
38 |
39 | function pmm_intersect (page_addr as addr_t, area_start as addr_t, area_end as addr_t) as boolean
40 | if ((area_start >= page_addr) and (area_start <= page_addr+PAGE_SIZE)) then return true
41 | if ((area_end >= page_addr) and (area_end <= page_addr+PAGE_SIZE)) then return true
42 | if ((area_start <= page_addr) and (area_end >= page_addr+PAGE_SIZE)) then return true
43 |
44 | return false
45 | end function
46 |
47 | sub pmm_init (mbinfo as multiboot_info ptr, zone as uinteger)
48 | '' 1. all memory is used by default
49 | '' 2. all free areas are put on the stack, but checked against reserved areas
50 | '' 3. reserved are:
51 | '' - memory used by the kernel code
52 | '' - video memory
53 | '' - modules and their cmdlines
54 | '' done
55 |
56 | '' initialization is slow, usage is fast (with a bitmap it's exactly the opposite)
57 | '' 1. mark the whole memory as used
58 | '' 2. free the memory marked as free in the memory-map
59 | '' 3. mark the whole memory used by the kernel as used
60 | '' 4. mark the video memory as used
61 | '' 5. mark the modules and their cmdline as used
62 |
63 | if ((mbinfo->flags and MULTIBOOT_INFO_MEM_MAP) = 0) then
64 | panic_error(!"Memory map not available!\n")
65 | end if
66 |
67 | assert((vmm_is_paging_ready() and cbool(zone = PMM_ZONE_NORMAL)) or ((not vmm_is_paging_ready()) and cbool(zone = PMM_ZONE_DMA24)))
68 |
69 | if (zone = PMM_ZONE_DMA24) then pmm_init_dma24()
70 |
71 | dim mmap as multiboot_mmap_entry ptr = cast(multiboot_mmap_entry ptr, mbinfo->mmap_addr)
72 | dim mmap_end as multiboot_mmap_entry ptr = cast(multiboot_mmap_entry ptr, (mbinfo->mmap_addr + mbinfo->mmap_length))
73 |
74 | '' free the memory listed in the memory-map
75 | while (mmap < mmap_end)
76 | '' only free regions that are marked as available
77 | if (mmap->type = MULTIBOOT_MEMORY_AVAILABLE) then
78 | '' don't free memory over 4GB, needs to be fixed to properly work on 64bit
79 | if (cuint((mmap->addr shr 32) and &hFFFFFFFF) = 0) then
80 | '' free each block of the region
81 | for addr as addr_t = mmap->addr to (mmap->addr+mmap->len-1) step PAGE_SIZE
82 | if (zone = PMM_ZONE_DMA24) and (addr >= 16*1024*1024) then exit for
83 |
84 | if (zone = PMM_ZONE_NORMAL) and (addr < 16*1024*1024) then continue for
85 |
86 | total_mem += PAGE_SIZE
87 |
88 | '' check if the block contains used memory
89 | '' does the block contain kernel memory?
90 | if (pmm_intersect(addr, caddr(kernel_start), caddr(kernel_end))) then continue for
91 |
92 | if (pmm_intersect(addr, mbinfo->cmdline, mbinfo->cmdline+PAGE_SIZE)) then continue for
93 |
94 | '' does the block contain video memory?
95 | if (pmm_intersect(addr, &hB8000, &hB8000+PAGE_SIZE)) then continue for
96 |
97 | '' iterate over the module list
98 | dim module_ptr as multiboot_mod_list ptr = cast(any ptr, mbinfo->mods_addr)
99 |
100 | for counter as uinteger = 1 to mbinfo->mods_count
101 | if (pmm_intersect(addr, module_ptr[counter-1].mod_start, module_ptr[counter-1].mod_end)) then
102 | continue for, for
103 | end if
104 |
105 | if (pmm_intersect(addr, module_ptr[counter-1].cmdline, module_ptr[counter-1].cmdline+PAGE_SIZE)) then
106 | continue for, for
107 | end if
108 | next
109 |
110 | '' &h1000 is reserved for the SMP trampoline-code
111 | if (addr = &h1000) then continue for
112 |
113 | '' free one block at a time
114 | if (zone = PMM_ZONE_NORMAL) then
115 | pmm_free_normal(cast(any ptr, cuint(addr)))
116 | free_mem += PAGE_SIZE
117 | elseif (zone = PMM_ZONE_DMA24) then
118 | pmm_free_dma24(cast(any ptr, cuint(addr)))
119 | free_mem += PAGE_SIZE
120 | end if
121 | next
122 | end if
123 | end if
124 | '' go to the next entry of the map
125 | mmap = cast(multiboot_mmap_entry ptr, cuint(mmap)+mmap->size+sizeof(multiboot_uint32_t))
126 | wend
127 | end sub
128 |
129 | function pmm_alloc (zone as uinteger = PMM_ZONE_NORMAL) as any ptr
130 | dim ret as any ptr = nullptr
131 |
132 | select case (zone)
133 | case PMM_ZONE_NORMAL:
134 | '' try to satisfy the request from the normal-zone
135 | ret = pmm_alloc_normal()
136 | if (ret = nullptr) then
137 | '' if it didn't work, fall through to the DMA24-zone
138 | ret = pmm_alloc(PMM_ZONE_DMA24)
139 | end if
140 | case PMM_ZONE_DMA24:
141 | ret = pmm_alloc_dma24()
142 | case else:
143 | panic_error(!"PMM: Invalid zone specification!\n")
144 | end select
145 |
146 | if (ret <> nullptr) then free_mem -= PAGE_SIZE
147 | return ret
148 | end function
149 |
150 | sub pmm_free (addr as any ptr)
151 | if (cuint(addr) < 16*1024*1024) then
152 | pmm_free_dma24(addr)
153 | else
154 | pmm_free_normal(addr)
155 | end if
156 | free_mem += PAGE_SIZE
157 | end sub
158 |
--------------------------------------------------------------------------------
/kernel/include/elf32.bi:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2013 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #pragma once
20 |
21 | type Elf32_Addr as uinteger
22 | type Elf32_Half as ushort
23 | type ELF32_Off as uinteger
24 | type Elf32_Sword as integer
25 | type Elf32_Word as uinteger
26 | type Elf32_Uchar as ubyte
27 |
28 | const ELF_MAGIC as uinteger = &h464C457F '' &h7F, 'E', 'L', 'F'
29 |
30 | const ELF_CLASS_NONE as ubyte = &h00
31 | const ELF_CLASS_32 as ubyte = &h01 '' 32bit file
32 | const ELF_CLASS_64 as ubyte = &h02 '' 64bit file
33 |
34 | const ELF_DATA_NONE as ubyte = &h00
35 | const ELF_DATA_2LSB as ubyte = &h01
36 | const ELF_DATA_2MSB as ubyte = &h02
37 |
38 | type ELF_IDENT_HEADER field=1
39 | EI_MAGIC(0 to 3) as ubyte
40 | EI_CLASS as ubyte '' 32 or 64 bit?
41 | EI_DATA as ubyte '' Little or Big Endian?
42 | EI_VERSION as ubyte '' same as e_version
43 | EI_PAD as uinteger '' reserved (zero)
44 | EI_PAD2 as uinteger '' reserved (zero)
45 | EI_NIDENT as ubyte '' size of the IDENT_HEADER
46 | end type
47 |
48 | '' for 32bit Processors:
49 | ' e_ident.EI_CLASS = ELF_CLASS_32
50 | ' e_ident.EI_DATA = ELF_DATA_2LSB
51 | ' e_machine = ELF_EM_386
52 |
53 | const ELF_ET_NONE as ushort = &h0000 '' no type
54 | const ELF_ET_REL as ushort = &h0001 '' relocatable
55 | const ELF_ET_EXEC as ushort = &h0002 '' executeable
56 | const ELF_ET_DYN as ushort = &h0003 '' Shared-Object-File
57 | const ELF_ET_CORE as ushort = &h0004 '' Corefile
58 | const ELF_ET_LOPROC as ushort = &hFF00 '' Processor-specific
59 | const ELF_ET_HIPROC as ushort = &h00FF '' Processor-specific
60 |
61 | const ELF_EM_NONE as ushort = &h0000 '' no type
62 | const ELF_EM_M32 as ushort = &h0001 '' AT&T WE 32100
63 | const ELF_EM_SPARC as ushort = &h0002 '' SPARC
64 | const ELF_EM_386 as ushort = &h0003 '' Intel 80386
65 | const ELF_EM_68K as ushort = &h0004 '' Motorola 68000
66 | const ELF_EM_88K as ushort = &h0005 '' Motorola 88000
67 | const ELF_EM_860 as ushort = &h0007 '' Intel 80860
68 | const ELF_EM_MIPS as ushort = &h0008 '' MIPS RS3000
69 |
70 | const ELF_EV_NONE as uinteger = &h00 '' invalid version
71 | const ELF_EV_CURRENT as uinteger = &h01 '' current version
72 |
73 | type Elf32_Ehdr field=1
74 | e_ident as ELF_IDENT_HEADER '' IDENT-HEADER (see above)
75 | e_type as Elf32_Half '' type of the ELF-file (relocatable, executeable, shared-object...)
76 | e_machine as Elf32_Half '' processor-type
77 | e_version as Elf32_Word '' ELF-version
78 | e_entry as Elf32_Addr '' virtual address of the entrypoint
79 | e_phoff as Elf32_Off '' offset of the program-header. zero if no program-header exists
80 | e_shoff as Elf32_Off '' offset of the section-header. zero if no section-header exists
81 | e_flags as Elf32_Word '' processor-specific flags
82 | e_ehsize as Elf32_Half '' size of the ELF-header
83 | e_phentsize as Elf32_Half '' size of one program-header entry
84 | e_phnum as Elf32_Half '' number of entries in the program-header. zero if no program-header exists
85 | e_shentsize as Elf32_Half '' size of one section-header entry
86 | e_shnum as Elf32_Half '' number of entries in the section-header. zero if no section-header exists
87 | e_shstrndex as Elf32_Half '' tells us which entry of the section-header is linked to the String-Table
88 | end type
89 |
90 | const ELF_PT_NULL as uinteger = &h00 '' invalid segment
91 | const ELF_PT_LOAD as uinteger = &h01 '' loadable segment
92 | const ELF_PT_DYNAMIC as uinteger = &h02 '' dynamic segment
93 | const ELF_PT_INTERP as uinteger = &h03 '' position of a zero-terminated string, which tells the interpreter
94 | const ELF_PT_NOTE as uinteger = &h04 '' universal segment
95 | const ELF_PT_SHLIB as uinteger = &h05 '' shared lib
96 | const ELF_PT_PHDIR as uinteger = &h06 '' tells position and size of the program-header
97 | const ELF_PT_LOPROC as uinteger = &h70000000 '' reserved
98 | const ELF_PT_HIPROC as uinteger = &h7FFFFFFF '' reserved
99 |
100 | const ELF_PF_X as uinteger = &h01 '' executeable segment
101 | const ELF_PF_W as uinteger = &h02 '' writeable segment
102 | const ELF_PF_R as uinteger = &h04 '' readable segment
103 |
104 | type Elf32_Phdr field=1
105 | p_type as Elf32_Word '' type of the segment (see constants above)
106 | p_offset as Elf32_Off '' offset of the segment (in the file)
107 | p_vaddr as Elf32_Addr '' virtual address to which we should copy the segment
108 | p_paddr as Elf32_Addr '' physical address
109 | p_filesz as Elf32_Word '' size of the segment in the file
110 | p_memsz as Elf32_Word '' size of the segment in memory
111 | p_flags as Elf32_Word '' flags (combination of constants above)
112 | p_align as Elf32_Word '' alignment. if zero or one, then no alignment is needed, otherwise the alignment has to be a power of two
113 | end type
114 |
--------------------------------------------------------------------------------
/kernel/src/smp.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "smp.bi"
20 | #include "kernel.bi"
21 | #include "debug.bi"
22 | #include "apic.bi"
23 | #include "mem.bi"
24 | #include "vmm.bi"
25 | #include "pmm.bi"
26 |
27 | #define uint_sig(a,b,c,d) (asc(a) or (asc(b) shl 8) or (asc(c) shl 16) or (asc(d) shl 24))
28 |
29 | const FP_SIGNATURE as uinteger = uint_sig("_", "M", "P", "_")
30 | const CT_SIGNATURE as uinteger = uint_sig("P", "C", "M", "P")
31 |
32 | function checksum (type_ptr as any ptr, size as uinteger) as ubyte
33 | dim checksum_byte as ubyte = 0
34 | dim bp as ubyte ptr = cast(ubyte ptr, type_ptr)
35 |
36 | for counter as uinteger = 0 to size-1 step 1
37 | checksum_byte += bp[counter]
38 | next counter
39 |
40 | return checksum_byte
41 | end function
42 |
43 | function find_floating_pointer_in_area (start as uinteger, size as uinteger) as smp_floating_pointer ptr
44 | dim floating_pointer as smp_floating_pointer ptr = cast(smp_floating_pointer ptr, start)
45 |
46 | while (cuint(floating_pointer) < (start + size))
47 | '' signature found
48 | if (floating_pointer->signature = FP_SIGNATURE) then
49 | '' check checksum, sum of all bytes must be zero
50 | if (checksum(floating_pointer, sizeof(smp_floating_pointer)) = 0) then
51 | '' structure found, return address
52 | return floating_pointer
53 | end if
54 | end if
55 | '' not found yet, search some more
56 | '' the structure is located on a 16-byte boundary (which is also the size of the FP), so adding 1 is ok
57 | floating_pointer += 1
58 | wend
59 | '' structure not found
60 | return nullptr
61 | end function
62 |
63 | function find_floating_pointer () as smp_floating_pointer ptr
64 | dim floating_pointer as smp_floating_pointer ptr
65 |
66 | floating_pointer = find_floating_pointer_in_area(0, &h400)
67 | if (floating_pointer <> nullptr) then return floating_pointer
68 |
69 | floating_pointer = find_floating_pointer_in_area(&h9FC00, &h400)
70 | if (floating_pointer <> nullptr) then return floating_pointer
71 |
72 | floating_pointer = find_floating_pointer_in_area(&hF0000, &h10000)
73 | return floating_pointer
74 | end function
75 |
76 | '' these symbols are generated by the linker to mark the embedded binary
77 | extern trampoline_start alias "_binary_obj_trampoline_bin_start" as byte
78 | extern trampoline_end alias "_binary_obj_trampoline_bin_end" as byte
79 |
80 | sub smp_init ()
81 | '' the trampoline is a flat binary embedded into the kernel, that needs
82 | '' to be copied to 0x1000
83 | dim v_mem as any ptr = vmm_kernel_automap(&h1000, PAGE_SIZE)
84 | memcpy(v_mem, @trampoline_start, (@trampoline_end) - (@trampoline_start))
85 | vmm_kernel_unmap(v_mem, PAGE_SIZE)
86 | lapic_startup_ipi(&h1000)
87 |
88 | '' FIXME:
89 | '' This code was based on the old SMP-spec, which has been replaced by
90 | '' ACPI-tables and is not working on newer systems. It is however the only
91 | '' way of starting pre-ACPI SMP systems.
92 | '' We should either drop this code, or refactor it into a fallback.
93 | #if 0
94 | dim floating_pointer as smp_floating_pointer ptr = find_floating_pointer()
95 | dim config_table as smp_config_table ptr
96 |
97 | if (floating_pointer = nullptr) then
98 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"floating pointer not found\n")
99 | return
100 | end if
101 |
102 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"floating pointer found: %X\n", cuint(floating_pointer))
103 |
104 | if (floating_pointer->features(0) = 0) then
105 | config_table = cast(any ptr, floating_pointer->config_table)
106 |
107 | if (config_table->signature <> CT_SIGNATURE) then
108 | printk(LOG_INFO !" -> signature of the config table is damaged!\n")
109 | return
110 | end if
111 |
112 | if (checksum(config_table, config_table->base_table_length) <> 0) then
113 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"checksum of the config table is wrong!\n")
114 | return
115 | end if
116 |
117 | '' pointer for the table
118 | dim entry as ubyte ptr = cast(ubyte ptr, cuint(config_table) + sizeof(smp_config_table))
119 | dim num_procs as uinteger = 0
120 |
121 | for entry_count as uinteger = 0 to config_table->entry_count-1 step 1
122 | select case *entry
123 | '' processor
124 | case CT_ENTRY_TYPES.PROCESSOR:
125 | num_procs += 1
126 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"processor #%u found\n", num_procs)
127 | entry += sizeof(cte_processor)
128 | '' bus
129 | case CT_ENTRY_TYPES.BUS:
130 | entry += sizeof(cte_bus)
131 | ''io apic
132 | case CT_ENTRY_TYPES.IO_APIC:
133 | '' TODO: put all the APIC's in an array
134 | dim ioapic as cte_io_apic ptr = cast(cte_io_apic ptr, entry)
135 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"I/O APIC found, ID: %X", cuint(ioapic->id))
136 | printk(LOG_INFO !", %X\n", cuint(ioapic->version))
137 | ioapic_base = ioapic->address
138 | entry += sizeof(cte_io_apic)
139 | '' io interrupt assignment
140 | case CT_ENTRY_TYPES.IO_INTERRUPT_ASSIGNMENT:
141 | entry += sizeof(cte_io_interrupt_assignment)
142 | '' local interrupt assignment
143 | case CT_ENTRY_TYPES.LOCAL_INTERRUPT_ASSIGNMENT:
144 | entry += sizeof(cte_local_interrupt_assignment)
145 | '' something went wrong
146 | case else:
147 | printk(LOG_INFO COLOR_GREEN "SMP: " COLOR_RESET !"config table entries corrupt!\n")
148 | return
149 | end select
150 | next
151 |
152 | end if
153 | #endif
154 | end sub
155 |
156 | '' we don't do much more here because FROST can't handle multiple processors atm
157 | '' TODO: proper SMP support
158 |
--------------------------------------------------------------------------------
/drivers/pci/src/main.bas:
--------------------------------------------------------------------------------
1 | #include "../../../kernel/include/syscall_defs.bi"
2 | #include "../../libfrost/frost.bi"
3 |
4 | const CONFIG_ADDRESS = &hCF8
5 | const CONFIG_DATA = &hCFC
6 |
7 | asm
8 | .global fb_ctor__main
9 | end asm
10 |
11 | '' request access to the textbuffer
12 | 'dim buffer as byte ptr
13 | '
14 | 'asm
15 | ' mov eax, syscalls.SYSCALL_MEMORY_ALLOCATE_PHYSICAL
16 | ' mov ebx, 4096
17 | ' mov ecx, &hb8000
18 | ' int &h62
19 | ' mov [buffer], eax
20 | 'end asm
21 |
22 | declare sub printd (format_string as const zstring, ...)
23 |
24 | sub outl (port as ushort, value as integer)
25 | asm
26 | movw dx, [port]
27 | mov eax, [value]
28 | outd dx, eax
29 | end asm
30 | end sub
31 |
32 | function inl (port as ushort) as integer
33 | asm
34 | movw dx, [port]
35 | ind eax, dx
36 | mov [function], eax
37 | end asm
38 | end function
39 |
40 | function PciRead (bus as integer, dev as integer, func as integer, offset as integer) as integer
41 | dim addr as integer = &h80000000 or (bus shl 16) or (dev shl 11) or (func shl 8) or (offset and &hFC)
42 | outl(CONFIG_ADDRESS, addr)
43 | return inl(CONFIG_DATA)
44 | end function
45 |
46 | sub PciWrite (bus as integer, dev as integer, func as integer, offset as integer, value as integer)
47 | dim addr as integer = &h80000000 or (bus shl 16) or (dev shl 11) or (func shl 8) or (offset and &hFC)
48 | outl(CONFIG_ADDRESS, addr)
49 | outl(CONFIG_DATA, value)
50 | end sub
51 |
52 | function PciIsDevicePresent (bus as integer, dev as integer) as boolean
53 | dim value as integer = PciRead(bus, dev, 0, 0)
54 | dim vendor as integer = value and &hFFFF
55 | dim device as integer = (value shr 16) and &hFFFF
56 |
57 | if vendor <> &hFFFF then
58 | printd(!"%X:%X\n", vendor, device)
59 | return true
60 | end if
61 |
62 | return false
63 | end function
64 |
65 | printd(!"Requesting PCI port access...\n")
66 | frost_syscall_port_request(CONFIG_ADDRESS)
67 | frost_syscall_port_request(CONFIG_ADDRESS+1)
68 | frost_syscall_port_request(CONFIG_ADDRESS+2)
69 | frost_syscall_port_request(CONFIG_ADDRESS+3)
70 | frost_syscall_port_request(CONFIG_DATA)
71 | frost_syscall_port_request(CONFIG_DATA+1)
72 | frost_syscall_port_request(CONFIG_DATA+2)
73 | frost_syscall_port_request(CONFIG_DATA+3)
74 |
75 | printd(!"Done.\n")
76 |
77 | for x as integer = 0 to 32
78 | PciIsDevicePresent(0, x)
79 | next
80 |
81 | while true
82 | 'frost_syscall_thread_yield()
83 | wend
84 |
85 | asm jmp $
86 |
87 |
88 | declare sub put_uint (number as uinteger, numerical_base as const ubyte = 10, minchars as const ubyte = 1, fillchar as ubyte = 32, lowercase as const boolean = false)
89 | declare sub put_int (number as integer, numerical_base as const ubyte = 10, minchars as const ubyte = 1, fillchar as const ubyte = 32)
90 |
91 | '' print one char
92 | sub putc (char as ubyte)
93 | dim chars (0 to 1) as ubyte
94 | chars(1) = 0
95 | chars(0) = char
96 |
97 | frost_syscall_43(@chars(0))
98 | end sub
99 |
100 | sub printd (format_string as const zstring, ...)
101 | dim fstr as const ubyte ptr = cast(const ubyte ptr, @format_string)
102 | dim arg as any ptr = va_first()
103 | dim c as uinteger = 0
104 | dim is_format as boolean = false
105 | var format_minchars = 1
106 | var format_fillchar = asc(" ")
107 |
108 | while (fstr[c] <> 0)
109 | if (is_format) then
110 | select case fstr[c]
111 | case asc("%")
112 | putc(fstr[c])
113 | is_format = false
114 | case asc("d"), asc("i")
115 | put_int(va_arg(arg, integer), 10, format_minchars, format_fillchar)
116 | arg = va_next(arg, integer)
117 | is_format = false
118 | case asc("u")
119 | put_uint(va_arg(arg, uinteger), 10, format_minchars, format_fillchar)
120 | arg = va_next(arg, uinteger)
121 | is_format = false
122 | case asc("x")
123 | put_uint(va_arg(arg, uinteger), 16, format_minchars, format_fillchar, true)
124 | arg = va_next(arg, uinteger)
125 | is_format = false
126 | case asc("X")
127 | put_uint(va_arg(arg, uinteger), 16, format_minchars, format_fillchar)
128 | arg = va_next(arg, uinteger)
129 | is_format = false
130 | case asc("c")
131 | putc(va_arg(arg, byte))
132 | arg = va_next(arg, byte)
133 | is_format = false
134 | case asc("s")
135 | dim s_it as uinteger = 0
136 | dim s_str as byte ptr = va_arg(arg, byte ptr)
137 | arg = va_next(arg, byte ptr)
138 |
139 | while (s_str[s_it] <> 0)
140 | putc(s_str[s_it])
141 | s_it += 1
142 | wend
143 |
144 | is_format = false
145 | case asc("0") to asc("9")
146 | if (fstr[c] = asc("0") and (fstr[c-1] = asc("%"))) then
147 | format_fillchar = asc("0")
148 | else
149 | format_minchars = format_minchars*10 + (fstr[c] - asc("0"))
150 | end if
151 | end select
152 | else
153 | select case fstr[c]
154 | case asc("%")
155 | is_format = true
156 | format_minchars = 1
157 | format_fillchar = asc(" ")
158 | case else
159 | putc(fstr[c])
160 | end select
161 | end if
162 |
163 | c += 1
164 | wend
165 | end sub
166 |
167 | '' print an uinteger with a given base and at least as many digits as given in minchars
168 | sub put_uint (number as uinteger, numerical_base as const ubyte = 10, minchars as const ubyte = 1, fillchar as ubyte = 32, lowercase as const boolean = false)
169 | if ((numerical_base > 36) or (numerical_base < 2)) then return
170 | if (minchars = 1) then fillchar = asc("0")
171 | dim chars(1 to 10) as ubyte
172 | dim num as ubyte
173 | dim counter as uinteger = 10
174 | dim rem_chars as integer = minchars
175 |
176 | do
177 | chars(counter) = 48+(number mod numerical_base)
178 | if (chars(counter)>57) then chars(counter) += 7
179 | counter -= 1
180 | number \= numerical_base
181 | rem_chars -= 1
182 | loop until ((number <= 0) and (rem_chars <= 0))
183 |
184 | for counter = 1 to 10
185 | if ((chars(counter)=0) and (num = 0)) then continue for
186 | if ((chars(counter)=asc("0")) and (num=0)) then
187 | putc(fillchar)
188 | else
189 | if (lowercase) and cast(boolean, (chars(counter) > 64)) then chars(counter) += 32
190 | putc(chars(counter))
191 | num = 1
192 | end if
193 | next
194 | end sub
195 |
196 | '' same game with integers. if the number is negative we just print a minus and then the number.
197 | sub put_int (number as integer, numerical_base as const ubyte = 10, minchars as const ubyte = 1, fillchar as const ubyte = 32)
198 | if ((numerical_base > 36) or (numerical_base < 2)) then return
199 | if (number<0) then
200 | putc(45)
201 | number = -number
202 | end if
203 | put_uint(cuint(number),numerical_base,minchars,fillchar)
204 | end sub
205 |
--------------------------------------------------------------------------------
/kernel/src/thread.bas:
--------------------------------------------------------------------------------
1 | /'
2 | ' FROST x86 microkernel
3 | ' Copyright (C) 2010-2017 Stefan Schmidt
4 | '
5 | ' This program is free software: you can redistribute it and/or modify
6 | ' it under the terms of the GNU General Public License as published by
7 | ' the Free Software Foundation, either version 3 of the License, or
8 | ' (at your option) any later version.
9 | '
10 | ' This program is distributed in the hope that it will be useful,
11 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ' GNU General Public License for more details.
14 | '
15 | ' You should have received a copy of the GNU General Public License
16 | ' along with this program. If not, see .
17 | '/
18 |
19 | #include "thread.bi"
20 | #include "process.bi"
21 | #include "pmm.bi"
22 | #include "vmm.bi"
23 | #include "kmm.bi"
24 | #include "mem.bi"
25 | #include "panic.bi"
26 | #include "video.bi"
27 | #include "modules.bi"
28 |
29 | DEFINE_LIST(thread_type)
30 |
31 | '' linked list of running threads
32 | dim shared running_threads_list as Listtype(thread_type)
33 | dim shared current_thread as thread_type ptr = nullptr
34 | dim shared idle_thread as thread_type ptr
35 |
36 | operator thread_type.new (size as uinteger) as any ptr
37 | return kmalloc(size)
38 | '' constructor is called automatically
39 | end operator
40 |
41 | operator thread_type.delete (buffer as any ptr)
42 | kfree(buffer)
43 | '' destructor is called automatically
44 | end operator
45 |
46 | constructor thread_type (process as process_type ptr, entry as any ptr, userstack_pages as uinteger, flags as ubyte = 0)
47 | '' assign id
48 | this.id = process->get_tid()
49 |
50 | '' set owning process
51 | this.parent_process = process
52 |
53 | '' set flags
54 | this.flags = flags
55 |
56 | '' set state
57 | this.state = THREAD_STATE_DISABLED
58 |
59 | '' insert it into the list of the process
60 | process->thread_list.insert_before(@this.process_threads)
61 |
62 | '' allocate a virtual memory area for the stack
63 | this.stack_area = process->a_s.allocate_area(userstack_pages)
64 |
65 | '' reserve physical memory and map the area
66 | for pagecounter as uinteger = 1 to userstack_pages
67 | dim p_addr as any ptr = pmm_alloc()
68 | dim v_addr as uinteger = cuint(this.stack_area->address) + (pagecounter-1)*PAGE_SIZE
69 |
70 | vmm_map_page(@process->context, cast(any ptr, v_addr), p_addr, VMM_FLAGS.USER_DATA)
71 | next
72 |
73 | '' reserve space for the kernel-stack
74 | this.kernelstack_p = pmm_alloc()
75 |
76 | '' map the kernel stack into the kernel's address space (unreachable from userspace)
77 | this.kernelstack_bottom = vmm_kernel_automap(this.kernelstack_p, PAGE_SIZE)
78 |
79 | '' create a pointer to the isf
80 | dim isf as interrupt_stack_frame ptr = this.kernelstack_bottom + PAGE_SIZE - sizeof(interrupt_stack_frame)
81 | this.isf = isf
82 |
83 | '' clear the whole structure
84 | memset(isf, 0, sizeof(interrupt_stack_frame))
85 |
86 | '' initialize the isf
87 | isf->eflags = &h0202
88 | isf->eip = cuint(entry)
89 | isf->esp = cuint(this.stack_area->address) + this.stack_area->pages*PAGE_SIZE
90 | isf->cs = &h18 or &h03
91 | isf->ss = &h20 or &h03
92 | end constructor
93 |
94 | sub thread_type.destroy ()
95 | if (current_thread = @this) then
96 | this.state = THREAD_STATE_KILL_ON_SCHEDULE
97 | this.flags or= THREAD_FLAG_RESCHEDULE
98 | return
99 | end if
100 |
101 | '' remove thread from the active thread list
102 | this.deactivate()
103 |
104 | '' remove thread from the threadlist of the process
105 | process_remove_thread(@this)
106 |
107 | '' unmap kernelstack
108 | vmm_unmap_range(@this.parent_process->context, this.kernelstack_bottom, 1)
109 |
110 | '' free kernelstack
111 | pmm_free(this.kernelstack_p)
112 |
113 | '' free the physical memory of the userspace stack
114 | for pagecounter as uinteger = 1 to this.stack_area->pages
115 | dim p_stack as any ptr = vmm_resolve(@this.parent_process->context, this.stack_area->address + (pagecounter-1)*PAGE_SIZE)
116 | pmm_free(p_stack)
117 | next
118 |
119 | '' unmap the userspace stack
120 | vmm_unmap_range(@this.parent_process->context, this.stack_area->address, this.stack_area->pages)
121 |
122 | '' delete the address space area
123 | delete this.stack_area
124 |
125 | '' free thread structure
126 | kfree(@this)
127 | end sub
128 |
129 | sub thread_type.activate ()
130 | if (this.state = THREAD_STATE_RUNNING) then
131 | panic_error("Kernel tried to activate an already activated thread!")
132 | end if
133 |
134 | '' set the state
135 | this.state = THREAD_STATE_RUNNING
136 |
137 | '' insert it into the running-thread-list
138 | running_threads_list.insert_before(@this.active_threads)
139 | end sub
140 |
141 | sub thread_type.deactivate ()
142 | this.state = THREAD_STATE_DISABLED
143 |
144 | this.active_threads.remove()
145 | end sub
146 |
147 | function schedule (isf as interrupt_stack_frame ptr) as thread_type ptr
148 | dim new_thread as thread_type ptr = current_thread
149 |
150 | dim it as Listtype(thread_type) ptr = iif(current_thread, @current_thread->active_threads, @running_threads_list)
151 | while (not running_threads_list.is_empty())
152 | it = it->get_next()
153 | if (it = @running_threads_list) then continue while
154 |
155 | dim t as thread_type ptr = it->get_owner()
156 |
157 | if (t->state = THREAD_STATE_KILL_ON_SCHEDULE) then
158 | t->destroy()
159 | continue while
160 | end if
161 |
162 | new_thread = t
163 | exit while
164 | wend
165 |
166 | if (running_threads_list.is_empty()) then
167 | new_thread = idle_thread
168 | end if
169 |
170 | if (current_thread <> nullptr) then
171 | if (new_thread->parent_process <> current_thread->parent_process) then
172 | '' IO bitmaps are process-wide, so unload the bitmap on process switch
173 | tss_ptr->io_bitmap_offset = TSS_IO_BITMAP_NOT_LOADED
174 | end if
175 | end if
176 |
177 | current_thread = new_thread
178 |
179 | return new_thread
180 | end function
181 |
182 | sub thread_switch (isf as interrupt_stack_frame ptr)
183 | dim old_process as process_type ptr = nullptr
184 | if (get_current_thread() <> nullptr) then
185 | old_process = get_current_thread()->parent_process
186 | end if
187 |
188 | dim new_thread as thread_type ptr = schedule(isf) '' select a new thread
189 |
190 | '' set his esp0 in the tss
191 | tss_ptr->esp0 = cuint(new_thread->isf) + sizeof(interrupt_stack_frame)
192 | '' set the esp0 for fast syscalls
193 | write_msr(MSR_IA32_SYSENTER_ESP, cuint(new_thread->isf) + sizeof(interrupt_stack_frame))
194 |
195 | '' load the new pagedir
196 | if ((new_thread->parent_process <> old_process) and (new_thread <> idle_thread)) then
197 | vmm_activate_context(@new_thread->parent_process->context)
198 | end if
199 | end sub
200 |
201 | function get_current_thread () as thread_type ptr
202 | return current_thread
203 | end function
204 |
205 | sub thread_idle ()
206 | do
207 | asm hlt
208 | loop
209 | end sub
210 |
211 | sub thread_create_idle_thread ()
212 | idle_thread = new thread_type(init_process, @thread_idle, 0)
213 | idle_thread->isf->cs = &h08
214 | idle_thread->isf->ss = &h10
215 |
216 | '' don't use thread_activate here, it's not a normal thread
217 | idle_thread->state = THREAD_STATE_RUNNING
218 | end sub
219 |
220 | sub set_io_bitmap ()
221 | tss_ptr->io_bitmap_offset = TSS_IO_BITMAP_OFFSET
222 |
223 | if (current_thread->parent_process->io_bitmap <> nullptr) then
224 | memcpy(@tss_ptr->io_bitmap(0), current_thread->parent_process->io_bitmap, &hFFFF\8)
225 | else
226 | memset(@tss_ptr->io_bitmap(0), &hFF, &hFFFF\8)
227 | end if
228 | end sub
229 |
--------------------------------------------------------------------------------