Compare commits

..

No commits in common. "master" and "struggles" have entirely different histories.

56 changed files with 835 additions and 966 deletions

View File

@ -11,10 +11,6 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
SET(CMAKE_SYSTEM_NAME Generic) SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_CROSSCOMPILING 1) SET(CMAKE_CROSSCOMPILING 1)
enable_language(ASM)
enable_language(C)
enable_language(CXX)
project(chroma) project(chroma)
SET(src_files SET(src_files
@ -33,10 +29,9 @@ SET(src_files
${CMAKE_SOURCE_DIR}/src/system/memory/liballoc.cpp ${CMAKE_SOURCE_DIR}/src/system/memory/liballoc.cpp
${CMAKE_SOURCE_DIR}/src/system/memory/physmem.c ${CMAKE_SOURCE_DIR}/src/system/memory/physmem.c
${CMAKE_SOURCE_DIR}/src/system/process/process.cpp ${CMAKE_SOURCE_DIR}/src/system/process/process.cpp
${CMAKE_SOURCE_DIR}/src/system/extern/extern_defs.cpp
${CMAKE_SOURCE_DIR}/src/drivers/elf.cpp ${CMAKE_SOURCE_DIR}/src/drivers/elf.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/devices.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/devices.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/io/ps2_keyboard.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/input/keyboard.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/io/apic.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/io/apic.cpp
${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp
) )
@ -46,7 +41,7 @@ SET(lib_files
${CMAKE_SOURCE_DIR}/src/lainlib/mutex/ticketlock.cpp ${CMAKE_SOURCE_DIR}/src/lainlib/mutex/ticketlock.cpp
${CMAKE_SOURCE_DIR}/src/lainlib/compression/lzgmini.c ${CMAKE_SOURCE_DIR}/src/lainlib/compression/lzgmini.c
${CMAKE_SOURCE_DIR}/src/lainlib/string/str.cpp ${CMAKE_SOURCE_DIR}/src/lainlib/string/str.cpp
${CMAKE_SOURCE_DIR}/src/lainlib/vector/vector.cpp ${CMAKE_SOURCE_DIR}/src/editor/EditorMain.cpp
) )
include_directories("inc" "D:/mingw/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++" "D:/mingw/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32") include_directories("inc" "D:/mingw/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++" "D:/mingw/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32")
@ -55,10 +50,6 @@ SET(src_no_sse
${CMAKE_SOURCE_DIR}/src/system/interrupts.cpp ${CMAKE_SOURCE_DIR}/src/system/interrupts.cpp
) )
SET(src_as
${CMAKE_SOURCE_DIR}/src/global/core-att.s
)
SET(src_preamble SET(src_preamble
${CMAKE_SOURCE_DIR}/src/global/crt0.o ${CMAKE_SOURCE_DIR}/src/global/crt0.o
${CMAKE_SOURCE_DIR}/src/global/crti.o ${CMAKE_SOURCE_DIR}/src/global/crti.o
@ -79,5 +70,5 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
add_executable(kernel) add_executable(kernel)
target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_epilogue}) target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_epilogue})
target_compile_options(kernel PRIVATE -ffreestanding -O0 -Wall -Wextra -Wall -Werror -fPIC -fno-exceptions -fno-omit-frame-pointer -mno-red-zone -fno-stack-protector -fno-strict-aliasing $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> -ggdb3) target_compile_options(kernel PRIVATE -ffreestanding -O0 -Wall -Wextra -Wall -Werror -fPIC -fno-exceptions -fno-omit-frame-pointer -mno-red-zone -fno-stack-protector -fno-rtti -ggdb3)
target_link_options(kernel PRIVATE -T ${CMAKE_SOURCE_DIR}/linker.ld -ffreestanding -O2 -nostdlib -nostartfiles -lgcc) target_link_options(kernel PRIVATE -T ${CMAKE_SOURCE_DIR}/linker.ld -ffreestanding -O2 -nostdlib -nostartfiles -lgcc)

View File

@ -38,55 +38,10 @@ It will compile the kernel, and create an OS image with `mkbootimg`.
### Linux ### Linux
The system for linux is a lot easier, but you *do* need an x86_64-elf-gcc cross compiler. You can get one from the AUR on Arch-based distros (like Manjaro), or make one yourself using [the OSDev Wiki guide](https://wiki.osdev.org/GCC_Cross-Compiler) The system for linux is a lot easier, but you *do* need an x86_64-elf-gcc cross compiler. You can get one from the AUR on Arch-based distros (like Manjaro), or make one yourself using [the OSDev Wiki guide](https://wiki.osdev.org/GCC_Cross-Compiler)
Simply run the `init.sh` to generate a makefile, then `make` to create the image file.
On the Chroma side, Simply run the `init.sh` to generate a makefile, then `make` to create the image file.
The generated IMG works in QEMU, or on a physical test device (unlike a lot of other hobby OSes!) The generated IMG works in QEMU, or on a physical test device (unlike a lot of other hobby OSes!)
This means you can use any emulator or hypervisor to run it. This means you can use any emulator or hypervisor to run it.
## Project structure
The repository has a lot of files and folders after setting up a workspace. This is a guide to all the files and folders.
```
File Location | Description
/
├── bin/ | Binary Output folder
│ └── img/ | Image Output folder.
│ └── chroma.img | Disk Image file, as an alternative to ISO below.
│ |
├── inc/ | Global header include folder.
│ ├── driver/ | Header files for the default driver implementations.
│ ├── editor/ | Header files for the builtin editor and debugger.
│ ├── kernel/ | Header files for the Chroma kernel itself.
│ └── lainlib/ | Header files for the Lainlib standard library.
│ |
├── src/ | Source files.
│ ├── assets/ | Assorted linkable files that will be bundled with the built image.
│ ├── drivers/ | Handling of the default driver implementations.
│ ├── editor/ | Handling of the builtin editor and debugger.
│ ├── global/ | Various files used in global objects (ie. the C RunTime, new core bootstrapping, etc)
│ ├── lainlib/ | Handling of the Lainlib standard library.
│ ├── system/ | Core Kernel files.
│ ├── video/ | Writing and drawing on the screen.
│ └── kernel.cpp | The primary kernel entry point.
│ |
├── tools/ | Auxiliary tools used in the buildsystem.
│ └── mkbootimg/ | Creates a bootable .img file based on the chroma.json configuration file below.
│ |
├── .gitignore | Git Repository Ignored Files
├── build_and_run.sh | shell script that builds the img file and runs it using run.sh below.
├── choma.bxrc | bxrc (Bochs Runtime Config) file for the Bochs emulator and debugger.
├── chroma.iso | ISO disc image file that can be loaded into a VM or onto a boot disk.
├── chroma.json | MkBootImg configuration file
├── CMakeLists.txt | Buildscript and CMake project configuration file.
├── LICENSE | Chroma's License. MIT License.
├── linker.ld | GCC linkerscript that places files and addresses at their expected positions.
├── post.sh | Postprocessing script; Generates the final img file, and attempts to update a VirtualBox configuration named "Chroma" to run this new file instead.
├── pre.sh | First-time setup script; generates the font file binary and generates the CMake buildscripts.
├── README.md | This file.
└── run.bat | Attempts to start a Virtualbox VM named "chroma".
```

View File

@ -2,7 +2,6 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "lainlib/vector/vector.h"
/************************ /************************
*** Team Kitty, 2021 *** *** Team Kitty, 2021 ***
@ -51,50 +50,7 @@ namespace Device {
}; };
}; };
class GenericKeyboard : public GenericDevice { // TODO: GenericKeyboard
public:
struct KeyboardData {
char Char;
char Scancode;
bool Pressed;
};
// This is an input device.
DeviceType GetType() const final {
return DeviceType::INTERFACE;
};
// Provided for utility checks.
static DeviceType GetRootType() {
return DeviceType::INTERFACE;
};
virtual bool isPressed(uint8_t) const = 0;
virtual uint8_t getLastPress() const = 0;
size_t readBuffer(void* dest, size_t index, size_t len) {
size_t lengthRead = len;
if (index > buffer.size()) {
return 0;
} else if (index + len > buffer.size()) {
lengthRead = sizeof(KeyboardData) - index; // TODO: wat?
}
memcpy((uint8_t*) dest, ((uint8_t*)buffer.data) + index, lengthRead);
return lengthRead;
}
size_t getBufferSize() {
return buffer.size();
}
protected:
lainlib::vector<KeyboardData> buffer;
};
// TODO: GenericDebugger // TODO: GenericDebugger
// TODO: GenericNetwork // TODO: GenericNetwork

View File

@ -1,39 +0,0 @@
#pragma once
#include <driver/generic/device.h>
/************************
*** Team Kitty, 2022 ***
*** Chroma ***
***********************/
extern char keys[128];
namespace Device {
class PS2Keyboard : public GenericKeyboard {
bool keyStates[128];
uint8_t lastPress = 0;
uint8_t* callback;
public:
PS2Keyboard();
// The instance of this singleton class.
static PS2Keyboard* driver;
const char* GetName() const {
return "PS2 Keyboard";
};
void Init();
void InterruptHandler();
void setState(bool state, uint8_t key);
bool isPressed(uint8_t key) const;
uint8_t getLastPress() const {
return keys[lastPress];
}
void SetCallback(uint32_t*);
};
}

28
inc/driver/keyboard.h Normal file
View File

@ -0,0 +1,28 @@
#include <kernel/chroma.h>
/************************
*** Team Kitty, 2020 ***
*** Chroma ***
***********************/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
char Char;
char Scancode;
bool Pressed;
} KeyboardData;
typedef void (*KeyboardCallback)(KeyboardData Frame);
extern KeyboardCallback KeyboardCallbacks[16];
int SetupKBCallback(void (*Handler)(KeyboardData Frame));
void UninstallKBCallback(int Index);
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,10 @@
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* /*
;* Memory map ;* Memory map
;* 0h - 600h reserved for the system ;* 0h - 600h reserved for the system
@ -152,3 +156,9 @@ typedef struct {
* MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++;
* until you reach bootboot->size */ * until you reach bootboot->size */
} __attribute__((packed)) bootinfo; } __attribute__((packed)) bootinfo;
#ifdef __cplusplus
}
#endif

View File

@ -9,6 +9,10 @@
* It also provides the symbols for the framebuffer and configuration file, which are both equually important. * It also provides the symbols for the framebuffer and configuration file, which are both equually important.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
#define UNUSED(x) (void)x #define UNUSED(x) (void)x
#include <stdint.h> #include <stdint.h>
@ -69,6 +73,7 @@ void WriteChar(const char character);
void WriteStringWithFont(const char* string); void WriteStringWithFont(const char* string);
void InitInterrupts();
void InitSerial(); void InitSerial();
void InitPrint(); void InitPrint();
@ -77,14 +82,12 @@ void SetupIDT();
int ParseKernelHeader(size_t InitrdPtr); int ParseKernelHeader(size_t InitrdPtr);
#ifdef __cplusplus
extern "C" {
#endif
void InitInterrupts();
int Main(); int Main();
void Exit(int code); void Exit(int code);
void SomethingWentWrong(const char* Message); void SomethingWentWrong(const char* Message);
#ifdef __cplusplus #ifdef __cplusplus
} } // extern "C"
#endif #endif

View File

@ -90,7 +90,7 @@ namespace ACPI {
MADT(); MADT();
void LogDump(); void LogDump();
void Init(); void Initialize();
// Get the byte of the end of the table. // Get the byte of the end of the table.
size_t GetEndOfTable(); size_t GetEndOfTable();
// Get all of the entries in the table, as an array. // Get all of the entries in the table, as an array.

View File

@ -47,7 +47,7 @@ namespace ACPI {
// RSDP Entries themselves. // RSDP Entries themselves.
struct RSDT { struct RSDT {
ACPIHeader Header; ACPIHeader Header;
uint32_t OtherSDTs[]; uint32_t* OtherSDTs;
} __attribute__((packed)); } __attribute__((packed));
RSDP(); RSDP();

View File

@ -32,18 +32,18 @@ class Core {
Core() {} Core() {}
Core(size_t LAPIC, size_t ID); Core(size_t LAPIC, size_t ID);
size_t ID = 0; size_t ID;
size_t LocalAPIC = 0; size_t LocalAPIC;
address_space_t* AddressSpace = nullptr; address_space_t* AddressSpace;
uint8_t* SyscallStack = 0; uint8_t* SyscallStack;
size_t StackAddress = 0; size_t StackAddress;
uint8_t StackData[Constants::Core::STACK_SIZE] = { 0 }; uint8_t StackData[Constants::Core::STACK_SIZE];
IDT CoreIDT = { 0, 0 }; IDT CoreIDT;
GDT CoreGDT = { 0, 0 }; GDT CoreGDT;
TSS64 CoreTSS = { }; TSS64 CoreTSS;
void LoadExtraRegisters(uint8_t* Data); void LoadExtraRegisters(uint8_t* Data);
void SaveExtraRegisters(uint8_t* Data); void SaveExtraRegisters(uint8_t* Data);
@ -53,17 +53,28 @@ class Core {
static Core* GetCurrent() { static Core* GetCurrent() {
size_t CoreID = 0; size_t CoreID = 0;
__asm__ __volatile__("mov %0, %%fs\n" : "=r"(CoreID) : :); __asm__ __volatile__("mov %0, %%fs\n" : "=r"(CoreID) : :);
return Processors[CoreID]; return &Processors[CoreID];
} }
static Core* GetCore(int ID) { return Processors[ID]; } static Core* GetCore(int ID) { return &Processors[ID]; }
static void PreInit();
static void Init(); static void Init();
private: private:
static Core* Processors[]; static Core Processors[];
// Initialization vectors for all new cores.
// Numbers derived from boot.h space.
// Specifically, the bootloader ROM.
enum Initialization {
PAGETABLES = 0x600,
STARTUP = 0x620,
STACK = 0x670,
GDT = 0x680,
IDT = 0x690
};
void Bootstrap(); void Bootstrap();
void SetupData(size_t ID);
}; } __attribute__((packed));

View File

@ -8,6 +8,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
uint16_t LowLimit; uint16_t LowLimit;
uint16_t BaseLow; uint16_t BaseLow;
@ -82,3 +86,7 @@ typedef struct __attribute__((packed)) {
uint16_t Length; uint16_t Length;
size_t Address; size_t Address;
} IDT; } IDT;
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -12,6 +12,7 @@ extern "C" {
extern const char* ExceptionStrings[]; extern const char* ExceptionStrings[];
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
size_t rip; size_t rip;
size_t cs; size_t cs;
@ -29,17 +30,12 @@ typedef struct __attribute__((packed)) {
size_t ss; size_t ss;
} EXCEPTION_FRAME; } EXCEPTION_FRAME;
typedef void (*IRQHandler)(INTERRUPT_FRAME* Frame); typedef void (*IRQHandler)(INTERRUPT_FRAME* Frame);
typedef struct { extern IRQHandler IRQ_Handlers[16];
IRQHandler handlers[8];
size_t numHandlers;
} IRQHandlerData;
extern IRQHandlerData IRQHandlers[32]; void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame));
size_t InstallIRQ(int IRQ, IRQHandler handler);
void UninstallIRQHandler(int IRQ, size_t ID);
__attribute__((no_caller_saved_registers)) void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt); __attribute__((no_caller_saved_registers)) void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
__attribute__((no_caller_saved_registers)) void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt); __attribute__((no_caller_saved_registers)) void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
@ -99,5 +95,5 @@ void IRQ14Handler(INTERRUPT_FRAME* Frame);
void IRQ15Handler(INTERRUPT_FRAME* Frame); void IRQ15Handler(INTERRUPT_FRAME* Frame);
#ifdef __cplusplus #ifdef __cplusplus
} } // extern "C"
#endif #endif

View File

@ -8,6 +8,10 @@
#define PAUSE __asm__ __volatile__("pause") #define PAUSE __asm__ __volatile__("pause")
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { typedef struct {
uint8_t ACK; uint8_t ACK;
uint8_t SelfTest; uint8_t SelfTest;
@ -18,6 +22,7 @@ typedef struct {
extern KBD_FLAGS KbdFlags; extern KBD_FLAGS KbdFlags;
DESC_TBL ReadGDT(void); DESC_TBL ReadGDT(void);
void WriteGDT(DESC_TBL GDTData); void WriteGDT(DESC_TBL GDTData);
@ -64,14 +69,12 @@ void Send8042(size_t);
void WriteSerialChar(const char); void WriteSerialChar(const char);
void WriteSerialString(const char*, size_t); void WriteSerialString(const char*, size_t);
#ifdef __cplusplus
extern "C" {
#endif
int SerialPrintf(const char* format, ...); int SerialPrintf(const char* format, ...);
int Printf(const char* Format, ...); int Printf(const char* Format, ...);
void* memcpy(void* dest, void const* src, size_t len); void* memcpy(void* dest, void const* src, size_t len);
void* memset(void* dst, int src, size_t len); void* memset(void* dst, int src, size_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,10 +1,13 @@
#pragma once #pragma once
#include <lainlib/lainlib.h> #ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <kernel/system/interrupts.h> #include <kernel/system/interrupts.h>
#include <lainlib/lainlib.h>
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
@ -38,18 +41,10 @@
#define CONCAT(x, y) x ## y #define CONCAT(x, y) x ## y
#define CONCAT2(x, y) CONCAT(x, y) #define CONCAT2(x, y) CONCAT(x, y)
#ifdef __cplusplus
extern "C" {
#endif
#define ASSERT(exp, error) \ #define ASSERT(exp, error) \
if(!(exp)) SomethingWentWrong(error); if(!(exp)) SomethingWentWrong(error);
// typedef char CONCAT2(static_assert, __LINE__) [(exp) ? 1 : -1] // typedef char CONCAT2(static_assert, __LINE__) [(exp) ? 1 : -1]
#ifdef __cplusplus
}
#endif
#define CLZ(num) (num ? __builtin_clzll(num) : 64) #define CLZ(num) (num ? __builtin_clzll(num) : 64)
#define IS_ALIGNED(addr) (((size_t) addr | 0xFFFFFFFFFFFFF000) == 0) #define IS_ALIGNED(addr) (((size_t) addr | 0xFFFFFFFFFFFFF000) == 0)
@ -147,8 +142,6 @@ extern "C" {
#define KERNEL_HEAP_REGION 0xFFFFE00080000000ull // Kernel Object Space (kmalloc will allocate into this region) #define KERNEL_HEAP_REGION 0xFFFFE00080000000ull // Kernel Object Space (kmalloc will allocate into this region)
#define KERNEL_HEAP_END 0xFFFFE000C0000000ull // End of Kernel Object Space #define KERNEL_HEAP_END 0xFFFFE000C0000000ull // End of Kernel Object Space
#define APIC_REGION 0x00000000FEE00000ull // Physical location of the APIC MMIO region.
#define DIRECT_REGION 0xFFFF800000000000ull #define DIRECT_REGION 0xFFFF800000000000ull
#define LOWER_REGION 0x0000000100000000ull // Lower Memory cutoff - 4GB #define LOWER_REGION 0x0000000100000000ull // Lower Memory cutoff - 4GB
@ -228,15 +221,10 @@ size_t AllocatorMaxBlockSize(void);
size_t AllocatorPoolOverhead(void); size_t AllocatorPoolOverhead(void);
size_t AllocatorAllocateOverhead(void); size_t AllocatorAllocateOverhead(void);
#ifdef __cplusplus
extern "C" {
#endif
size_t AlignUpwards(size_t Pointer, size_t Alignment); size_t AlignUpwards(size_t Pointer, size_t Alignment);
size_t AlignDownwards(size_t Pointer, size_t Alignment); size_t AlignDownwards(size_t Pointer, size_t Alignment);
void* AlignPointer(const void* Pointer, size_t Alignment); void* AlignPointer(const void* Pointer, size_t Alignment);
#ifdef __cplusplus
}
#endif
/************************************************************ /************************************************************
@ -247,10 +235,6 @@ extern size_t memstart;
extern size_t end; extern size_t end;
#ifdef __cplusplus
extern "C" {
#endif
void ListMemoryMap(); void ListMemoryMap();
void InitMemoryManager(); void InitMemoryManager();
@ -284,7 +268,6 @@ void TraversePageTables();
void* memcpy(void* dest, void const* src, size_t len); void* memcpy(void* dest, void const* src, size_t len);
/********************************************* /*********************************************
* C h r o m a A l l o c a t o r * C h r o m a A l l o c a t o r
**********************************************/ **********************************************/

View File

@ -1,5 +1,9 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
@ -175,3 +179,7 @@ typedef struct {
extern pci_device_t** pci_root_devices; extern pci_device_t** pci_root_devices;
extern pci_entry_t* pci_map; extern pci_entry_t* pci_map;
#ifdef __cplusplus
}
#endif

View File

@ -3,6 +3,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
// This file contains all of the bitmap fonts made by me (Curle) and taken from the public domain // This file contains all of the bitmap fonts made by me (Curle) and taken from the public domain
// eg. http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm // eg. http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm
@ -464,3 +468,7 @@ const unsigned char bitfont_block[32][8] = {
{ 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259E (boxes top right and bottom left) { 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259E (boxes top right and bottom left)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF}, // U+259F (boxes right and bottom) { 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF}, // U+259F (boxes right and bottom)
}; };
#ifdef __cplusplus
}
#endif

View File

@ -5,6 +5,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* Drawing routines for screen manipulation. * Drawing routines for screen manipulation.
* This will be pulled out into the Helix library soon. * This will be pulled out into the Helix library soon.
@ -56,3 +60,7 @@ void DrawLineRoundedRect(size_t x, size_t y, size_t width, size_t height, size_t
void DrawFilledCircle(size_t centerX, size_t centerY, size_t radius); void DrawFilledCircle(size_t centerX, size_t centerY, size_t radius);
void DrawLineCircle(size_t centerX, size_t centerY, size_t radius); void DrawLineCircle(size_t centerX, size_t centerY, size_t radius);
void DrawLineCircleCorners(size_t centerX, size_t centerY, size_t radius, char cornerMask); void DrawLineCircleCorners(size_t centerX, size_t centerY, size_t radius, char cornerMask);
#ifdef __cplusplus
}
#endif

View File

@ -28,6 +28,10 @@
#ifndef _LIBLZG_H_ #ifndef _LIBLZG_H_
#define _LIBLZG_H_ #define _LIBLZG_H_
#ifdef __cplusplus
extern "C" {
#endif
#define LZG_VERSION "1.0.10" /**< @brief LZG library version string */ #define LZG_VERSION "1.0.10" /**< @brief LZG library version string */
#define LZG_VERNUM 0x0100000a /**< @brief LZG library version number (strictly */ #define LZG_VERNUM 0x0100000a /**< @brief LZG library version number (strictly */
/* incremental) */ /* incremental) */
@ -316,4 +320,8 @@ lzg_uint32_t LZG_Version(void);
*/ */
const char* LZG_VersionString(void); const char* LZG_VersionString(void);
#ifdef __cplusplus
}
#endif
#endif // _LIBLZG_H_ #endif // _LIBLZG_H_

View File

@ -3,6 +3,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <kernel/system/pci.h> #include <kernel/system/pci.h>
@ -179,3 +183,7 @@ void E1000InterruptFired(INTERRUPT_FRAME* InterruptContext);
uint8_t* E1000GetMAC(e1000_device_t* Device); uint8_t* E1000GetMAC(e1000_device_t* Device);
// Send a packet // Send a packet
int E1000Send(e1000_device_t* Device, const void* Data, uint16_t Length); int E1000Send(e1000_device_t* Device, const void* Data, uint16_t Length);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,9 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Chroma *** *** Chroma ***
@ -21,5 +25,5 @@
#include <lainlib/compression/lzg.h> #include <lainlib/compression/lzg.h>
#ifdef __cplusplus #ifdef __cplusplus
#include <lainlib/vector/vector.h> } // extern "C"
#endif #endif

View File

@ -1,5 +1,9 @@
#include <stdbool.h> #include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct list_entry { typedef struct list_entry {
struct list_entry* Previous; struct list_entry* Previous;
struct list_entry* Next; struct list_entry* Next;
@ -32,3 +36,7 @@ bool ListIsEmpty(list_entry_t* Head);
for(pos = UNSAFE_CAST((head)->next, typeof(*(pos)), member); &pos->member != (head); pos = LISTNEXT(pos, member)) for(pos = UNSAFE_CAST((head)->next, typeof(*(pos)), member); &pos->member != (head); pos = LISTNEXT(pos, member))
#define LASTENTRY 0 #define LASTENTRY 0
#ifdef __cplusplus
}
#endif

View File

@ -5,6 +5,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile int spinlock_t; typedef volatile int spinlock_t;
/* A set of macros that acquire and release a mutex spinlock. */ /* A set of macros that acquire and release a mutex spinlock. */
@ -18,3 +22,7 @@ typedef volatile int spinlock_t;
#define SPUNLOCK(name) \ #define SPUNLOCK(name) \
__sync_synchronize(); \ __sync_synchronize(); \
name = 0; name = 0;
#ifdef __cplusplus
}
#endif

View File

@ -7,6 +7,11 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file provides a simple implementation of a ticket-based locking system. /* This file provides a simple implementation of a ticket-based locking system.
* You should probably prefer Spinlock over Ticketlock. * You should probably prefer Spinlock over Ticketlock.
* *
@ -17,10 +22,6 @@
* *
*/ */
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { typedef struct {
size_t NowServing; size_t NowServing;
size_t NextTicket; size_t NextTicket;

View File

@ -6,6 +6,14 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
size_t strlen(const char* String); size_t strlen(const char* String);
bool strcmp(char* a, const char* b); bool strcmp(char* a, const char* b);
#ifdef __cplusplus
}
#endif

View File

@ -1,129 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <kernel/system/memory.h>
/************************
*** Team Kitty, 2022 ***
*** Lainlib ***
***********************/
// integer typedefs
using u32 = uint32_t;
namespace lainlib {
template<typename T>
struct vector {
T& operator [] (u32 i) {
return this->data[i];
}
T operator [] (u32 i) const {
return this->data[i];
}
u32 size() {
return bytes / sizeof(T);
}
template<typename access_type>
access_type handle_read(const void *buf) {
access_type v;
memcpy(&v,buf,sizeof(access_type));
return v;
}
template<typename access_type>
void handle_write(void *buf, access_type v) {
memcpy(buf,&v,sizeof(access_type));
}
// insert at end as a var as a raw set of bytes into the Array
template<typename Y>
void emplace_back(Y v) {
const u32 len = sizeof(v);
reserve(len);
// actually write in the data
handle_write(&data[size()], v);
bytes += len;
}
T pop() {
const T v = data[size() - 1];
bytes -= sizeof(v);
return v;
}
void reserve_raw(u32 size) {
capacity = size;
data = (T*)krealloc(data, size);
}
void resize(u32 in) {
const u32 len = in * sizeof(T);
const u32 old_len = size();
reserve_raw( bytes);
bytes = len;
// default initialize the new elements
for(u32 i = old_len; i < size(); i++) {
data[i] = {};
}
}
// make sure there is enough left for the allocation we are doing
void reserve(u32 size) {
const u32 free_size = capacity - bytes;
// we have room to just dump this in
if(free_size >= size) {
return;
} else {
const u32 new_capacity = (capacity + size) * 2;
reserve_raw(new_capacity);
}
}
// raw mem read and writes over the array
T read_var(u32 idx) {
return handle_read<T>(data[idx]);
}
template<typename Y>
void write_var(u32 idx, T v) {
return handle_write(data[idx], v);
}
// insert raw memory block into the array
void push_mem(const void* newData, u32 size)
{
reserve(size);
memcpy(data[bytes], newData, size);
bytes += size;
}
void destroy() {
if(data) {
kfree(data);
data = nullptr;
}
bytes = 0;
capacity = 0;
}
T* data = nullptr;
// in raw bytes
u32 bytes = 0;
u32 capacity = 0;
};
}

View File

@ -22,7 +22,7 @@ Device::GenericStorage* StorageDevicesArray[MAX_STORAGE_DEVICES];
size_t CurrentStorageDevice = 0; size_t CurrentStorageDevice = 0;
// Internal storage. TODO: Make this not a pain to maintain // Internal storage. TODO: Make this not a pain to maintain
const char* DeviceNames[] = {"Storage", "Internal", "Peripheral", "Networking"}; const char* DeviceNames[] = {"Storage", "Keyboard", "Networking"};
// Add a device pointer to the managed list. // Add a device pointer to the managed list.
@ -30,7 +30,7 @@ void Device::RegisterDevice(Device::GenericDevice* Device) {
DevicesArray[CurrentDevice] = Device; DevicesArray[CurrentDevice] = Device;
Device->DeviceID = CurrentDevice; Device->DeviceID = CurrentDevice;
CurrentDevice++; CurrentDevice++;
SerialPrintf("[ DEV] Registered device %d called %s of type %s\r\n", CurrentDevice - 1, Device->GetName(), SerialPrintf("[DEVICE] Registered device %d called %s of type %s\r\n", CurrentDevice - 1, Device->GetName(),
DeviceNames[Device->GetType()]); DeviceNames[Device->GetType()]);
} }

View File

@ -0,0 +1,160 @@
#include <kernel/chroma.h>
#include <driver/keyboard.h>
/************************
*** Team Kitty, 2020 ***
*** Chroma ***
***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file contains (mostly unused) implementations of a full PS/2 keyboard driver.
*
* It provides provisions for full 2-way communication, as well as auxiliary key commands.
* //TODO: Media keys?
*
* Once this driver is to a workable state, I would like to start adding a proper keyboard buffer,
* which will integrate with a window system.
*
*/
KBD_FLAGS KbdFlags;
char keys[128] = {
0, 27,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
0,
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#',
0,
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
0,
'*', 0,
' ', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
'-',
0,
0,
0,
'+',
0,
0,
0,
0,
0,
0, 0, 0,
0,
0,
0,
};
KeyboardCallback KeyboardCallbacks[16] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static int CurrentCallback = 0;
int SetupKBCallback(void (* Handler)(KeyboardData Frame)) {
KeyboardCallbacks[CurrentCallback++] = Handler;
return CurrentCallback;
}
void UninstallKBCallback(int Number) {
KeyboardCallbacks[Number] = NULL; // 0 is used in the common check to make sure that the function is callable.
// This removes this callback from that check, ergo the function will no longer be called.
}
void KbdEcho() {
if (!KbdFlags.EchoCount) {
if (!KbdFlags.Echo) {
Send8042(0xEE);
}
} else {
KbdFlags.EchoCount = 0;
KbdFlags.Echo = 0;
}
}
void UpdateKeyboard(uint8_t msg) {
switch (msg) {
case 0x0:
KbdFlags.Error = 1;
//ResendBuffer();
break;
case 0xAA:
KbdFlags.SelfTest = 1;
break;
case 0xEE:
KbdFlags.Echo = 0;
KbdFlags.EchoCount = 2;
KbdEcho();
break;
case 0xFA:
KbdFlags.ACK = 1;
//ProgressBuffer();
break;
case 0xFC:
case 0xFD:
KbdFlags.SelfTest = 0;
KbdFlags.Error = 1;
//RestartKbd();
break;
case 0xFE:
//ResendBuffer();
break;
case 0xFF:
KbdFlags.Error = 1;
//ResendBuffer();
break;
default:
break;
}
KeyboardData data = (KeyboardData) {
.Char = msg > 0x80 && msg < 0xD8 ? keys[msg - 0x80] : keys[msg],
.Scancode = static_cast<char>(msg),
.Pressed = !(msg > 0x80 && msg < 0xD8),
};
void (* Handler)(KeyboardData data);
for (size_t handlerNum = 0; handlerNum < 16; handlerNum++) {
Handler = KeyboardCallbacks[handlerNum];
if (Handler) {
Handler(data);
}
}
}
void Send8042(size_t info) {
for (size_t i = 0; i < 8; i++) {
unsigned char chr = (unsigned char) info;
if (chr != 0) {
WritePort(0x60, chr, 1);
WaitFor8042();
}
}
}
void WaitFor8042() {
bool full = true;
while (full) {
full = ReadPort(0x64, 1) & 1;
}
}
#ifdef __cplusplus
}
#endif

View File

@ -2,8 +2,6 @@
#include <kernel/system/acpi/madt.h> #include <kernel/system/acpi/madt.h>
#include <kernel/system/io.h> #include <kernel/system/io.h>
#include <kernel/system/memory.h> #include <kernel/system/memory.h>
#include "kernel/system/core.hpp"
#include "kernel/chroma.h"
/************************ /************************
*** Team Kitty, 2021 *** *** Team Kitty, 2021 ***
@ -53,7 +51,7 @@ void APIC::Enable() {
} }
void APIC::SendEOI() { void APIC::SendEOI() {
*((volatile uint32_t*) 0xfee000B0) = 0; WriteRegister(Registers::EOI, 0);
} }
bool APIC::IsReady() { bool APIC::IsReady() {
@ -61,20 +59,14 @@ bool APIC::IsReady() {
} }
void APIC::Init() { void APIC::Init() {
Device::RegisterDevice(this); SerialPrintf("[ACPI] Enabling APICs...");
SerialPrintf("[ ACPI] Enabling APICs...\r\n");
SerialPrintf("[ ACPI] Memory Mapping APICs..\r\n");
for (int i = 0; i < 3; i++) {
MapVirtualPage(&KernelAddressSpace, (size_t) Address + i * PAGE_SIZE, (size_t) Address + i * PAGE_SIZE, 3);
}
Address = (void*) ACPI::MADT::instance->LocalAPICBase; Address = (void*) ACPI::MADT::instance->LocalAPICBase;
SerialPrintf("[ MADT] The APIC of this core is at 0x%p\r\n", (size_t) Address);
// TODO: Check whether the identity mapping covers this address
if (Address == nullptr) { if (Address == nullptr) {
SerialPrintf("[ ACPI] Unable to locate APICs.\r\n"); SerialPrintf("[ACPI] Unable to locate APICs.");
for (;;) { } for (;;) { }
} }
@ -82,9 +74,13 @@ void APIC::Init() {
WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10)); WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10));
Enable(); Enable();
SerialPrintf("[ ACPI] Enabling Global APIC..\r\n"); // Disable PIC1 and 2
WritePort(0x21, 0xFF, 1);
WritePort(0xA1, 0xFF, 1);
SerialPrintf("[ACPI] Enabling Global APIC..");
IOAPICs = ACPI::MADT::instance->GetIOApicEntries(); IOAPICs = ACPI::MADT::instance->GetIOApicEntries();
SerialPrintf("[ ACPI] Enabling Interrupt Source Overrides..\r\n"); SerialPrintf("[ACPI] Enabling Interrupt Source Overrides..");
ISOs = ACPI::MADT::instance->GetISOEntries(); ISOs = ACPI::MADT::instance->GetISOEntries();
Ready = true; Ready = true;
@ -112,8 +108,8 @@ void APIC::InitializeCore(int Core, size_t EntryPoint) {
WriteRegister(Registers::ICR1, 0x600 | ((uint32_t) (EntryPoint / PAGE_SIZE))); WriteRegister(Registers::ICR1, 0x600 | ((uint32_t) (EntryPoint / PAGE_SIZE)));
} }
void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CoreID, int Status) { void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int Core, int Status) {
UNUSED(Core);
size_t temp = Vector; size_t temp = Vector;
int64_t target = -1; int64_t target = -1;
@ -125,7 +121,7 @@ void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CoreID,
} }
if (target == -1) { if (target == -1) {
SerialPrintf("[ APIC] No ISO found when setting up redirect.\r\n"); SerialPrintf("[APIC] No ISO found when setting up redirect.");
return; return;
} }
@ -138,24 +134,6 @@ void APIC::SetInternal(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CoreID,
if (!Status) if (!Status)
temp |= (1 << 16); temp |= (1 << 16);
temp |= (((size_t) Core::GetCore(CoreID)->LocalAPIC) << 56); // TODO
uint32_t IORegister = (GSI - IOAPICs[target]->GSI) * 2 + 0x10;
SerialPrintf("[ APIC] Setting interrupt %u, redirect %u, on LAPIC %u(%u) of core %u, address 0x%p, register 0x%p, data 0x%p\r\n", GSI, Vector, Core::GetCore(CoreID)->LocalAPIC, target, CoreID, IOAPICs[target]->Address, IORegister, temp);
WriteIO(IOAPICs[target]->Address, IORegister, (uint32_t) temp);
WriteIO(IOAPICs[target]->Address, IORegister + 1, (uint32_t)(temp >> 32));
}
void APIC::Set(int CPU, uint8_t IRQ, int Enabled) {
for(size_t i = 0; ISOs[i] != 0; i++) {
// We need to make sure we take into account the overrides, so check whether any IRQ is overriden
if (ISOs[i]->IRQ == IRQ) {
SetInternal(ISOs[i]->IRQ + 0x20, ISOs[i]->Interrupt, ISOs[i]->Flags, CPU, Enabled);
return;
}
}
// If there are no overrides, we can just remap it upwards
SetInternal(IRQ + 0x20, IRQ, 0, CPU, Enabled);
} }

View File

@ -1,170 +0,0 @@
#include <driver/io/ps2_keyboard.h>
#include <kernel/chroma.h>
#include "driver/io/apic.h"
/************************
*** Team Kitty, 2022 ***
*** Chroma ***
***********************/
char keys[128] = {
0, 27,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
0,
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#',
0,
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
0,
'*', 0,
' ', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
'-',
0,
0,
0,
'+',
0,
0,
0,
0,
0,
0, 0, 0,
0,
0,
0,
};
char shiftedKeys[128] = {
0,
0, // ESC
33, // !
64, // @
35, // #
36, // $
37, // %
94, // ^
38, // &
42, // *
40, // (
41, // )
95, // _
43, // +
0,
0,
81, // Q
87,
69,
82,
84,
89,
85,
73,
79,
80, // P
123, // {
125, // }
0,
10,
65, // A
83,
68,
70,
71,
72,
74,
75,
76, // L
58, // :
34, // "
126, // ~
0,
124, // |
90, // Z
88,
67,
86,
66,
78,
77, // M
60, // <
62, // >
63, // ?
0,
0,
0,
32, // SPACE
};
Device::PS2Keyboard* Device::PS2Keyboard::driver;
using namespace Device;
void IRQRedirect(INTERRUPT_FRAME* irq) {
UNUSED(irq);
PS2Keyboard::driver->InterruptHandler();
}
PS2Keyboard::PS2Keyboard() {
driver = this;
}
void PS2Keyboard::setState(bool state, uint8_t key) {
keyStates[key] = state;
if(state)
lastPress = key;
else
lastPress = 0;
if(callback != nullptr)
callback[key] = state;
}
bool PS2Keyboard::isPressed(uint8_t key) const {
return keyStates[key];
}
void PS2Keyboard::Init() {
Device::RegisterDevice(this);
buffer.reserve(100);
for (size_t idx = 0; idx < 128; idx++) {
keyStates[idx] = false;
}
InstallIRQ(1, IRQRedirect);
}
void PS2Keyboard::InterruptHandler() {
uint8_t state = ReadPort(0x64, 1);
// while keyboard has input and the buffer is not empty
while (state & 1 && !(state & 0x20)) {
uint8_t keycode = ReadPort(0x60, 1);
uint8_t scancode = keycode & 0x7f;
uint8_t keystate = !(keycode & 0x80);
if (keystate)
SerialPrintf("[ KEY] %c pressed.\r\n", keys[scancode]);
state = ReadPort(0x64, 1);
setState(keystate, scancode);
KeyboardData data { keys[scancode], (char) scancode, (bool) keystate };
buffer.emplace_back(data);
}
}
void PS2Keyboard::SetCallback(uint32_t* data) {
callback = (uint8_t*) data;
for (size_t idx = 0; idx < 128; idx++) {
callback[idx] = false;
}
}

View File

@ -4,6 +4,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* /*
* This file provides utility functions for parsing ELF headers. * This file provides utility functions for parsing ELF headers.
* This exists so that the kernel can find itself for remapping, * This exists so that the kernel can find itself for remapping,
@ -88,3 +92,7 @@ int ParseKernelHeader(size_t InitrdPtr) {
return flag; return flag;
} }
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,5 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <driver/keyboard.h>
#include <kernel/video/draw.h> #include <kernel/video/draw.h>
#include <editor/main.h> #include <editor/main.h>
@ -10,9 +11,11 @@
/** /**
* Contains startup and setup routines for the Chroma Editor. * Contains startup and setup routines for the Chroma Editor.
*/ */
static KeyboardCallback KernelHandler;
void Editor::StartEditor(int callbackID) { void Editor::StartEditor(int callbackID) {
UNUSED(callbackID); KernelHandler = KeyboardCallbacks[callbackID];
EditorLayout layout; EditorLayout layout;
layout.ScreenHeight = PrintInfo.screenHeight; layout.ScreenHeight = PrintInfo.screenHeight;
layout.ScreenWidth = PrintInfo.screenWidth; layout.ScreenWidth = PrintInfo.screenWidth;

View File

@ -1,131 +0,0 @@
#************************
#*** Team Kitty, 2021 ***
#*** Chroma ***
#************************
# Initial startup routines for new cores.
# New cores start in 16 bit real mode.
# Because of this, this is the only necessary assembler file in the OS.
# First, bring them up to Protected and Long mode.
# Then enable all necessary auxiliary features.
# Pass off to the CPP code to handle the heavy work, we just want the core running.
.code16
.equ BASE, 0x1000
.global stack
.extern initcpu
.extern coreidt
.extern ProtectedGDT
.extern LongGDT
# 16-bit startup.
# Initialize registers.
# Load GDT
# Set flags
# Immediately jump to protected mode.
.global startCore
startCore:
cli
mov $0x0, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
.code64
lgdt ProtectedGDT
.code16
mov %cr0, %eax
or $0x1, %ax
mov %eax, %cr0
ljmpl $0x8, $startCore32
.code32
# Protected mode setup.
# Set page tables
# Set PAE
# Immediately jump to long mode.
.section .text
startCore32:
mov $0x10, %bx
mov %bx, %ds
mov %bx, %es
mov %bx, %ss
mov $0xA000, %eax
mov %eax, %cr3
mov %cr4, %eax # Enable PAE
or $32, %eax # 1 << 5
or $128, %eax # 1 << 7
mov %eax, %cr4
mov $0xC0000080, %ecx
rdmsr
or $256, %eax # 1 << 8
wrmsr
mov %cr0, %eax
or $2147483648, %eax # 1 << 31
mov %eax, %cr0
.code64
lgdt LongGDT
.code32
ljmp $0x8, $startCore64
# Long mode setup.
# Prepare registers.
# Set flags
# Load the final GDT and IDT
# Jump to the leave function.
.code64
startCore64:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
mov $0x0, %ax
mov %ax, %ds
mov %ax, %gs
lgdt LongGDT
lidt coreidt
mov $0x0, %rbp
push $0
popf
mov (leave), %rax
jmp leave
# Final setup.
# Set some flags in registers.
# Jump into C++ code.
leave:
push %rbp
mov %cr0, %rax
btr $2, %eax
bts $1, %eax
mov %rax, %cr0
mov %cr4, %rax
bts $9, %eax
bts $10, %eax
mov %rax, %cr4
call initcpu
.global endCore
endCore:

View File

@ -1,29 +1,27 @@
.intel_syntax noprefix ;************************
#************************ ;*** Team Kitty, 2021 ***
#*** Team Kitty, 2021 *** ;*** Chroma ***
#*** Chroma *** ;************************
#************************
# Initial startup routines for new cores. ; Initial startup routines for new cores.
# New cores start in 16 bit real mode. ; New cores start in 16 bit real mode.
# Because of this, this is the only necessary assembler file in the OS. ; Because of this, this is the only necessary assembler file in the OS.
# First, bring them up to Protected and Long mode. ; First, bring them up to Protected and Long mode.
# Then enable all necessary auxiliary features. ; Then enable all necessary auxiliary features.
# Pass off to the CPP code to handle the heavy work, we just want the core running. ; Pass off to the CPP code to handle the heavy work, we just want the core running.
.intel_syntax [bits 16]
BASE equ 0x1000
.code16 global stack
.equ BASE, 0x1000 extern initcpu
.global stack extern coreidt
.extern initcpu extern coregdt
.extern coreidt global startCore
.extern coregdt startCore:
.global startCore
cli cli
mov ax, 0x0 mov ax, 0x0
mov ds, ax mov ds, ax
@ -40,9 +38,9 @@
jmp 0x8:(startCore32 - startCore + BASE) jmp 0x8:(startCore32 - startCore + BASE)
.code32 [bits 32]
.section .text section .text
startCore32: startCore32:
mov bx, 0x10 mov bx, 0x10
mov ds, bx mov ds, bx
@ -69,7 +67,7 @@ startCore32:
lgdt [gdt_long - startCore + BASE] lgdt [gdt_long - startCore + BASE]
jmp 8:(startCore64 - startCore + BASE) jmp 8:(startCore64 - startCore + BASE)
.code64 [bits 64]
startCore64: startCore64:
mov ax, 0x10 mov ax, 0x10
mov ds, ax mov ds, ax

View File

@ -1,35 +1,42 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <kernel/video/draw.h> #include <kernel/video/draw.h>
#include <driver/keyboard.h>
#include <editor/main.h> #include <editor/main.h>
#include "kernel/system/acpi/rsdt.h"
#include "kernel/system/acpi/madt.h"
#include "driver/io/apic.h"
#include "driver/io/ps2_keyboard.h"
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file is the entry point to the system. /* This file is the entry point to the system.
* It dictates the order of operations of everything the kernel actually does. * It dictates the order of operations of everything the kernel actually does.
* If a function isn't fired here, directly or indirectly, it is not run. * If a function isn't fired here, directly or indirectly, it is not run.
*/ */
bool KernelLoaded = false; static bool KernelLoaded = false;
address_space_t KernelAddressSpace; address_space_t KernelAddressSpace;
size_t KernelAddr = (size_t) &LoadAddr; size_t KernelAddr = (size_t) &LoadAddr;
size_t KernelEnd = (size_t) &end; size_t KernelEnd = (size_t) &end;
void PrintPressedChar(KeyboardData data);
int CharPrinterCallbackID; int CharPrinterCallbackID;
void TrackInternalBuffer(Device::GenericKeyboard::KeyboardData data); void TrackInternalBuffer(KeyboardData data);
int InternalBufferID; int InternalBufferID;
size_t BufferLength = 0; size_t BufferLength = 0;
char* InternalBuffer; char* InternalBuffer;
#ifdef __cplusplus
}
#endif
/** /**
* C++ code! Scary! * C++ code! Scary!
* This is a temporary measure to experiment with the Editor system. * This is a temporary measure to experiment with the Editor system.
@ -63,7 +70,9 @@ extern "C" int Main(void) {
PrepareCPU(); PrepareCPU();
PCIEnumerate(); PCIEnumerate();
InitMemoryManager(); InitMemoryManager();
InitPaging(); InitPaging();
Printf("Paging complete. System initialized.\n\r"); Printf("Paging complete. System initialized.\n\r");
@ -77,24 +86,26 @@ extern "C" int Main(void) {
SetForegroundColor(0x00FFFFFF); SetForegroundColor(0x00FFFFFF);
CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar);
Device::APIC::driver = new Device::APIC(); InternalBufferID = SetupKBCallback(&TrackInternalBuffer);
Device::PS2Keyboard::driver = new Device::PS2Keyboard();
ACPI::RSDP::instance->Init(0);
ACPI::MADT::instance->Init();
Core::PreInit();
Device::APIC::driver->Init();
Device::PS2Keyboard::driver->Init();
Core::Init();
for (;;) { } for (;;) { }
return 0;
}
extern "C" void PrintPressedChar(KeyboardData data) {
if (!KernelLoaded) return;
if (data.Pressed) {
SerialPrintf("Key pressed: [\\%c (%x)]\r\n", data.Char, data.Scancode);
Printf("%c", data.Char);
} else {
SerialPrintf("Key released: [\\%c]\r\n", data.Char);
}
} }
/*
extern "C" void TrackInternalBuffer(KeyboardData data) { extern "C" void TrackInternalBuffer(KeyboardData data) {
if (!data.Pressed) return; if (!data.Pressed) return;
@ -128,7 +139,8 @@ extern "C" void TrackInternalBuffer(KeyboardData data) {
InternalBuffer[BufferLength] = data.Char; InternalBuffer[BufferLength] = data.Char;
BufferLength++; BufferLength++;
} }
}*/ }
extern "C" void SomethingWentWrong(const char* Message) { extern "C" void SomethingWentWrong(const char* Message) {
SerialPrintf("Assertion failed! %s\r\n", Message); SerialPrintf("Assertion failed! %s\r\n", Message);

View File

@ -27,6 +27,10 @@
#include <lainlib/lainlib.h> #include <lainlib/lainlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/*-- PRIVATE -----------------------------------------------------------------*/ /*-- PRIVATE -----------------------------------------------------------------*/
/* Internal definitions */ /* Internal definitions */
@ -188,3 +192,7 @@ lzg_uint32_t LZG_Decode(const unsigned char *in, lzg_uint32_t insize,
else else
return decodedSize; return decodedSize;
} }
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,10 @@
*** Lainlib *** *** Lainlib ***
************************/ ************************/
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* This file handles all the logic for interfacing with the E1000 networking device. * This file handles all the logic for interfacing with the E1000 networking device.
* This card is labelled either the Intel I217, or Intel Gigabit 82577LM. * This card is labelled either the Intel I217, or Intel Gigabit 82577LM.
@ -351,3 +355,7 @@ int E1000Send(e1000_device_t* Device, const void* Data, uint16_t Length) {
return 0; return 0;
} }
#ifdef __cplusplus
}
#endif

View File

@ -5,6 +5,9 @@
*** Lainlib *** *** Lainlib ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
struct mac_address { struct mac_address {
uint8_t MAC[6]; uint8_t MAC[6];
@ -22,3 +25,7 @@ struct ethernet_packet {
uint16_t Type; uint16_t Type;
uint8_t Payload[]; uint8_t Payload[];
}; };
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,8 @@
#include <lainlib/list/list.h> #include <lainlib/list/list.h>
#ifdef __cplusplus
extern "C" {
#endif
void ListAdd(list_entry_t* Head, list_entry_t* New) { void ListAdd(list_entry_t* Head, list_entry_t* New) {
New->Next = Head->Next; New->Next = Head->Next;
@ -26,3 +29,7 @@ void ListRemove(list_entry_t* Entry) {
bool ListIsEmpty(list_entry_t* Head) { bool ListIsEmpty(list_entry_t* Head) {
return Head->Next == Head; return Head->Next == Head;
} }
#ifdef __cplusplus
}
#endif

View File

@ -2,7 +2,9 @@
#define PAUSE __asm__ __volatile__("pause") #define PAUSE __asm__ __volatile__("pause")
#ifdef __cplusplus
extern "C" { extern "C" {
#endif
void TicketLock(ticketlock_t* Lock) { void TicketLock(ticketlock_t* Lock) {
size_t Ticket = __atomic_fetch_add(&Lock->NextTicket, 1, __ATOMIC_RELAXED); size_t Ticket = __atomic_fetch_add(&Lock->NextTicket, 1, __ATOMIC_RELAXED);
@ -15,8 +17,7 @@ void TicketLock(ticketlock_t* Lock) {
bool TicketAttemptLock(ticketlock_t* Lock) { bool TicketAttemptLock(ticketlock_t* Lock) {
size_t Ticket = __atomic_load_8(&Lock->NowServing, __ATOMIC_RELAXED); size_t Ticket = __atomic_load_8(&Lock->NowServing, __ATOMIC_RELAXED);
__sync_synchronize(); __sync_synchronize();
return __atomic_compare_exchange_8(&Lock->NowServing, &Ticket, Ticket + 1, false, __ATOMIC_ACQUIRE, return __atomic_compare_exchange_8(&Lock->NowServing, &Ticket, Ticket + 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
__ATOMIC_RELAXED);
} }
void TicketUnlock(ticketlock_t* Lock) { void TicketUnlock(ticketlock_t* Lock) {
@ -25,4 +26,6 @@ void TicketUnlock(ticketlock_t* Lock) {
__atomic_store_8(&Lock->NowServing, NextTicket, __ATOMIC_RELEASE); __atomic_store_8(&Lock->NowServing, NextTicket, __ATOMIC_RELEASE);
} }
#ifdef __cplusplus
} }
#endif

View File

@ -7,6 +7,10 @@
*** Lainlib *** *** Lainlib ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
size_t strlen(const char* String) { size_t strlen(const char* String) {
size_t Len = 0; size_t Len = 0;
while(String[Len] != '\0') { while(String[Len] != '\0') {
@ -24,3 +28,7 @@ bool strcmp(char* a, const char* b) {
bI++; bI++;
} }
} }
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +0,0 @@
#include <lainlib/lainlib.h>
/************************
*** Team Kitty, 2022 ***
*** Lainlib ***
***********************/

View File

@ -18,8 +18,8 @@ size_t MADT::GetEndOfTable() {
return ((size_t) &Header->Header) + Header->Header.Length; return ((size_t) &Header->Header) + Header->Header.Length;
} }
void MADT::Init() { void MADT::Initialize() {
SerialPrintf("[ ACPI] Loading Multiple APIC Descriptor Tables..\r\n"); SerialPrintf("[ACPI] Loading Multiple APIC Descriptor Tables..");
Address = ACPI::RSDP::instance->FindEntry("APIC"); Address = ACPI::RSDP::instance->FindEntry("APIC");
Header = reinterpret_cast<MADTHeader*>(Address); Header = reinterpret_cast<MADTHeader*>(Address);
@ -40,7 +40,6 @@ MADT::IOAPICEntry** MADT::GetIOApicEntries() {
if (table->Type == MADT::Type::IOAPIC) { if (table->Type == MADT::Type::IOAPIC) {
MADT::IOAPICEntry* io_apic = reinterpret_cast<MADT::IOAPICEntry*>(table); MADT::IOAPICEntry* io_apic = reinterpret_cast<MADT::IOAPICEntry*>(table);
MapVirtualPage(&KernelAddressSpace, io_apic->Address, io_apic->Address, 3);
entries[count] = (MADT::IOAPICEntry*) ((size_t) io_apic); entries[count] = (MADT::IOAPICEntry*) ((size_t) io_apic);
count++; count++;
} }

View File

@ -61,28 +61,23 @@ void* RSDP::GetFACP(RSDT* Root) {
void RSDP::Init(size_t RSDP) { void RSDP::Init(size_t RSDP) {
UNUSED(RSDP); UNUSED(RSDP);
SerialPrintf("[ ACPI] Loading ACPI subsystem..\r\n"); SerialPrintf("[ACPI] Loading ACPI subsystem..");
Descriptor = (DescriptorV2*) GetRSDP(); Descriptor = (DescriptorV2*) GetRSDP();
Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT); Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT);
SerialPrintf("[ RSDP] Dumping RSDT. Table at 0x%p..\r\n", (size_t) Table); SerialPrintf("[RSDP] Dumping RSDT..");
size_t entries = (Table->Header.Length - sizeof(Table->Header)) / 4; auto* table = reinterpret_cast<RSDP::RSDT*>(TO_DIRECT(Descriptor->Header.RSDT));
SerialPrintf("[ RSDP] Found %u entries.\r\n", entries); size_t entries = (table->Header.Length - sizeof(table->Header)) / 4;
// For each entry: if valid, search for the specified name. // For each entry: if valid, search for the specified name.
for (size_t i = 0; i < entries; i++) { for (size_t i = 0; i < entries; i++) {
if (Table->OtherSDTs[i] == 0x0) if (table->OtherSDTs[i] == 0x0)
continue; continue;
ACPIHeader* header = (ACPIHeader*) ((size_t) 0 + (uint32_t) Table->OtherSDTs[i]); ACPIHeader* header = reinterpret_cast<ACPIHeader*>(table->OtherSDTs[i]);
char signature[5]; SerialPrintf("[RSDP] Entry %d: Signature %.4s, OEM %.6s\n", i, header->Signature, header->OEMID);
memcpy(signature, header->Signature, 4);
signature[4] = '\0';
char oem[7];
memcpy(oem, header->OEMID, 6);
oem[6] = '\0';
SerialPrintf("[ RSDP] Entry %d: Signature %s, OEM %s\n", i, signature, oem);
} }
} }

View File

@ -7,14 +7,17 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
extern size_t startCore;
extern size_t endCore;
int Cores = 0; int Cores = 0;
volatile bool Ready = false; volatile bool Ready = false;
Core* Core::Processors[Constants::Core::MAX_CORES]; Core Core::Processors[Constants::Core::MAX_CORES];
TSS64 Tasks[Constants::Core::MAX_CORES]; TSS64 Tasks[Constants::Core::MAX_CORES];
ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES]; ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES];
extern "C" [[noreturn]] void initcpu() { extern "C" void initcpu() {
// Init APIC // Init APIC
WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10)); WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10));
Device::APIC::driver->Enable(); Device::APIC::driver->Enable();
@ -22,6 +25,7 @@ extern "C" [[noreturn]] void initcpu() {
__asm__ __volatile__("mov %%fs, %0" : : "r" (Device::APIC::driver->GetCurrentCore()) : ); __asm__ __volatile__("mov %%fs, %0" : : "r" (Device::APIC::driver->GetCurrentCore()) : );
SerialPrintf("[CORE] Core %d ready.\r\n", Device::APIC::driver->GetCurrentCore()); SerialPrintf("[CORE] Core %d ready.\r\n", Device::APIC::driver->GetCurrentCore());
// TODO: New GDT
__asm__ __volatile__("cli"); __asm__ __volatile__("cli");
Ready = true; Ready = true;
__asm__ __volatile__("sti"); __asm__ __volatile__("sti");
@ -34,29 +38,22 @@ Core::Core(size_t APIC, size_t ID) {
GetCore(ID)->LocalAPIC = APIC; GetCore(ID)->LocalAPIC = APIC;
Bootstrap(); Bootstrap();
//SetupData(ID); SetupData(ID);
Device::APIC::driver->InitializeCore(APIC, reinterpret_cast<size_t>(initcpu)); Device::APIC::driver->InitializeCore(APIC, CORE_BOOTSTRAP);
while (!Ready) { while (Ready != true) {
__asm__ __volatile__ ("nop"); __asm__ ("nop");
} }
Ready = false; Ready = false;
} }
void Core::PreInit() {
for (size_t i = 0; i < Constants::Core::MAX_CORES; i++) {
Processors[i] = new Core();
}
}
void Core::Init() { void Core::Init() {
using namespace ACPI; using namespace ACPI;
Ready = false; Ready = false;
SerialPrintf("[ CORE] Enabling Multiprocessing\r\n"); SerialPrintf("[CORE] Enabling Multiprocessing\n");
memset(Tasks, 0, Constants::Core::MAX_CORES * sizeof(TSS64)); memset(Tasks, 0, Constants::Core::MAX_CORES * sizeof(TSS64));
for (size_t i = 0; i < Constants::Core::MAX_CORES; i++) for (size_t i = 0; i < Constants::Core::MAX_CORES; i++)
@ -68,6 +65,8 @@ void Core::Init() {
// While there are more entries in the table.. // While there are more entries in the table..
while ((size_t) table < MADT::instance->GetEndOfTable()) { while ((size_t) table < MADT::instance->GetEndOfTable()) {
// Move to the next entry (by skipping the length of the current entry)
table = (MADT::RecordTableEntry*) (((size_t) table) + table->Length);
// Check for a LAPIC record (which indicates a unique physical core) // Check for a LAPIC record (which indicates a unique physical core)
if (table->Type == MADT::Type::LAPIC) { if (table->Type == MADT::Type::LAPIC) {
// Find the data for the LAPIC with a reinterpret // Find the data for the LAPIC with a reinterpret
@ -80,30 +79,48 @@ void Core::Init() {
// Move to the next core if there is one. // Move to the next core if there is one.
Cores++; Cores++;
} }
// Move to the next entry (by skipping the length of the current entry)
table = (MADT::RecordTableEntry*) (((size_t) table) + table->Length);
} }
SerialPrintf("[ CORE] Found %d core(s).\r\n", Cores); SerialPrintf("[CORE] Found %d cores.\n", Cores);
if (Cores > 1) if (Cores > 1)
SerialPrintf("[ CORE] Bringing up other cores.\r\n"); SerialPrintf("[CORE] Bringing up other cores.\n");
// For each non-bootstrap core, initialize the necessary data and populate the array. // For each non-bootstrap core, initialize the necessary data and populate the array.
for (int i = 0; i < Cores; i++) { for (int i = 0; i < Cores; i++) {
SerialPrintf("[CORE] Enabling core %d.\n", i);
if (Device::APIC::driver->GetCurrentCore() != LAPICs[i]->Core) { if (Device::APIC::driver->GetCurrentCore() != LAPICs[i]->Core)
SerialPrintf("[ CORE] Enabling core %d.\r\n", i); Processors[i] = Core(LAPICs[i]->APIC, LAPICs[i]->Core);
delete Processors[i];
Core* c = new Core(LAPICs[i]->APIC, LAPICs[i]->Core);
Processors[i] = c;
}
} }
} }
void Core::Bootstrap() { void Core::Bootstrap() {
// TODO size_t coreStarterLen = endCore - startCore;
for (size_t i = 0; i < coreStarterLen + 2; i += PAGE_SIZE)
MapVirtualPage(AddressSpace, CORE_BOOTSTRAP + i, CORE_BOOTSTRAP + i, 0);
memcpy((void*) CORE_BOOTSTRAP, &startCore, coreStarterLen);
} }
void Core::SetupData(size_t Core) {
// Write page tables
GetCore(Core)->AddressSpace->PML4 = GetCurrent()->AddressSpace->PML4;
*((size_t*) Initialization::PAGETABLES) = (size_t) GetCore(Core)->AddressSpace->PML4;
// Prepare stack
memset(GetCore(Core)->StackData, 0, Constants::Core::STACK_SIZE);
*((size_t*) Initialization::STACK) = (size_t) GetCore(Core)->StackData + Constants::Core::STACK_SIZE;
// GDT = 0x680
// IDT = 0x690
__asm__ __volatile__("sgdt (0x680)\n sidt (0x690)");
// Set startup address
*((size_t*) Initialization::STARTUP) = (size_t) &initcpu;
}
void Core::StackTrace(size_t Cycles) { void Core::StackTrace(size_t Cycles) {
StackFrame* stack; StackFrame* stack;

View File

@ -1,12 +1,15 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <kernel/system/interrupts.h> #include <kernel/system/interrupts.h>
#include "driver/io/apic.h"
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This class provides functions for setting up and preparing the CPU for the things the kernel will do. /* This class provides functions for setting up and preparing the CPU for the things the kernel will do.
* Mainly, it allows you to: * Mainly, it allows you to:
* *
@ -41,11 +44,6 @@ __attribute__((aligned(64))) static volatile size_t InitGDT[5] = {
0 0
}; };
__attribute__((aligned(64))) static DESC_TBL CoreGDT = {
.Limit = sizeof(InitGDT),
.Base = (size_t) InitGDT
};
__attribute__((aligned(64))) static volatile TSS64 TSSEntries; __attribute__((aligned(64))) static volatile TSS64 TSSEntries;
__attribute__((aligned(64))) static volatile IDT_GATE IDTEntries[256]; __attribute__((aligned(64))) static volatile IDT_GATE IDTEntries[256];
@ -67,17 +65,53 @@ static void RefreshCS() {
void PrepareCPU() { void PrepareCPU() {
SetupInitialGDT(); SetupInitialGDT();
SetupIDT(); SetupIDT();
//SetupExtensions(); //SetupExtensions();
InitInterrupts(); InitInterrupts();
/* In either case, we tell the Master PIC it's been read to receive any IRQ. */
WritePort(0x20, 0x20, 1);
} }
/*void SetupExtensions() {
// Enable SSE
size_t CR0 = ReadControlRegister(0);
CR0 &= ~(1 << 2);
CR0 |= 1;
WriteControlRegister(0, CR0);
// Enable OSXSAVE and gang
size_t CR4 = ReadControlRegister(4);
CR4 |= (1 << 9);
CR4 |= (1 << 10);
CR4 |= (1 << 18);
WriteControlRegister(4, CR4);
// Enable AVX (and AVX-512 in future)
CR0 = ReadExtendedControlRegister(0);
SerialPrintf("XCR0 is currently %x.\n", CR0);
CR0 |= (1 << 0);
CR0 |= (1 << 1);
CR0 |= (1 << 2);
CR0 |= (1 << 5);
CR0 |= (1 << 6);
CR0 |= (1 << 7);
SerialPrintf("About to write xcr0: %x\n", CR0);
WriteExtendedControlRegister(0, CR0);
}
*/
void SetupInitialGDT() { void SetupInitialGDT() {
DESC_TBL GDTData;
size_t TSSBase = (uint64_t) (&TSSEntries); size_t TSSBase = (uint64_t) (&TSSEntries);
uint16_t TSSLower = (uint16_t) TSSBase; uint16_t TSSLower = (uint16_t) TSSBase;
@ -85,13 +119,15 @@ void SetupInitialGDT() {
uint8_t TSSMid2 = (uint8_t) (TSSBase >> 24); uint8_t TSSMid2 = (uint8_t) (TSSBase >> 24);
uint32_t TSSHigher = (uint32_t) (TSSBase >> 32); uint32_t TSSHigher = (uint32_t) (TSSBase >> 32);
GDTData.Limit = sizeof(InitGDT) - 1;
GDTData.Base = (size_t) InitGDT;
((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseLow = TSSLower; ((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseLow = TSSLower;
((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseMid1 = TSSMid1; ((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseMid1 = TSSMid1;
((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseMid2 = TSSMid2; ((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseMid2 = TSSMid2;
((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseHigh = TSSHigher; ((TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]))->BaseHigh = TSSHigher;
WriteGDT(CoreGDT); WriteGDT(GDTData);
WriteTSR(3 << 3); WriteTSR(3 << 3);
RefreshCS(); RefreshCS();
} }
@ -226,10 +262,13 @@ void SetupIDT() {
SetISR(46, (size_t) IRQ14Handler); SetISR(46, (size_t) IRQ14Handler);
SetISR(47, (size_t) IRQ15Handler); SetISR(47, (size_t) IRQ15Handler);
for (size_t i = 0; i < 32; i++) {
IRQHandlers[i] = {{}, 0 }; //TODO: ISRs 32 to 256
}
WriteIDT(IDTData); WriteIDT(IDTData);
} }
#ifdef __cplusplus
}
#endif

View File

@ -1,55 +0,0 @@
/************************
*** Team Kitty, 2022 ***
*** Chroma ***
***********************/
#include <kernel/system/descriptors.h>
/**
* Contains definitions that are used by external files.
* That means, independent programs or assembler files.
*/
/**
* The template GDT entry for a newly initialized core.
* Protected Mode.
* TODO: Document what the entries here are.
*/
__attribute__((aligned(64))) size_t ProtectedGDTEntry[3] = {
0,
0x00CF9A000000FFFF,
0x00CF92000000FFFF
};
/**
* The GDT table value to be loaded into each newly initialized core.
* Protected Mode.
*/
DESC_TBL ProtectedGDT = {
.Limit = sizeof(ProtectedGDTEntry) - 1,
.Base = (size_t) &ProtectedGDTEntry
};
/**
* The template GDT entry for a newly initialized core.
* Long Mode.
* TODO: Document what the entries here are.
*/
__attribute__((aligned(64))) size_t LongGDTEntry[3] = {
0,
0x00AF98000000FFFF,
0x00CF92000000FFFF
};
/**
* The GDT table value to be loaded into each newly initialized core.
* Long Mode.
*/
DESC_TBL LongGDT = {
.Limit = sizeof(LongGDTEntry) - 1,
.Base = (size_t) &LongGDTEntry
};

View File

@ -2,13 +2,16 @@
#include <kernel/video/draw.h> #include <kernel/video/draw.h>
#include <kernel/system/interrupts.h> #include <kernel/system/interrupts.h>
#include <stdbool.h> #include <stdbool.h>
#include "driver/io/apic.h"
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file contains all of the ISR and IRQ /* This file contains all of the ISR and IRQ
* (Interrupt Service Request) functions. * (Interrupt Service Request) functions.
* *
@ -38,10 +41,6 @@
* these having a size_t input as an error code. * these having a size_t input as an error code.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
const char* ExceptionStrings[] = { const char* ExceptionStrings[] = {
"Division by Zero", "Division by Zero",
"Debug", "Debug",
@ -77,7 +76,15 @@ const char* ExceptionStrings[] = {
"Reserved" "Reserved"
}; };
IRQHandlerData IRQHandlers[32]; typedef void (* IRQHandler)(INTERRUPT_FRAME* Frame);
IRQHandler IRQ_Handlers[16] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
typedef unsigned long long int uword_t;
/* All of the ISR routines call this function for now. /* All of the ISR routines call this function for now.
! This function is NOT leaf, and it might clobber the stack. ! This function is NOT leaf, and it might clobber the stack.
@ -117,83 +124,114 @@ void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception
which was set up earlier by irq_install.*/ which was set up earlier by irq_install.*/
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) {
// First we need to define a function pointer.. // First we need to define a function pointer..
IRQHandlerData handler; void (* Handler)(INTERRUPT_FRAME* Frame);
/* We set all uninitialized routines to 0, so the if(handler) check here allows us to /* We set all uninitialized routines to 0, so the if(handler) check here allows us to
safely tell whether we've actually got something for this IRQ. */ safely tell whether we've actually got something for this IRQ. */
handler = IRQHandlers[Interrupt]; Handler = IRQ_Handlers[Interrupt];
if (handler.numHandlers > 0) { // If there's something there,
//SerialPrintf("[ IRQ] IRQ %d raised!\r\n", Interrupt); if (Handler) {
// Call the handlers SerialPrintf("[ IRQ] IRQ %d raised!\r\n", Interrupt);
for (size_t i = 0; i < handler.numHandlers; i++) // Call the handler.
handler.handlers[i](Frame); Handler(Frame);
} }
/* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */
if (Interrupt > 7)
WritePort(0xA0, 0x20, 1);
/* In either case, we tell the Master PIC it's been read to receive any IRQ. */
WritePort(0x20, 0x20, 1);
Device::APIC::driver->SendEOI();
} }
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
/* However, in order to actually be able to receive IRQs, we need to remap the PICs. */ /* However, in order to actually be able to receive IRQs, we need to remap the PICs. */
void RemapIRQControllers() { void RemapIRQControllers() {
/* 0x20 is the Master PIC, /* 0x20 is the Master PIC,
0xA0 is the Slave PIC. */ 0xA0 is the Slave PIC. */
WritePort(0x20, 0x11, 1);
WritePort(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4, 1); // starts the initialization sequence (in cascade mode) WritePort(0xA0, 0x11, 1);
WritePort(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4, 1); WritePort(0x21, 0x20, 1);
WritePort(PIC1_DATA, 32, 1); // ICW2: Master PIC vector offset WritePort(0xA1, 0x28, 1);
WritePort(PIC2_DATA, 32 + 8, 1); // ICW2: Slave PIC vector offset WritePort(0x21, 0x04, 1);
WritePort(PIC1_DATA, 4, 1); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) WritePort(0xA1, 0x02, 1);
WritePort(PIC2_DATA, 2, 1); // ICW3: tell Slave PIC its cascade identity (0000 0010) WritePort(0x21, 0x01, 1);
WritePort(0xA1, 0x01, 1);
WritePort(PIC1_DATA, ICW4_8086, 1); WritePort(0x21, 0x0, 1);
WritePort(PIC2_DATA, ICW4_8086, 1); WritePort(0xA1, 0x0, 1);
WritePort(PIC1_DATA, 0xFF, 1); // restore saved masks.
WritePort(PIC2_DATA, 0xFF, 1);
} }
/* In order to actually handle the IRQs, though, we need to tell the kernel *where* the handlers are. */ /* In order to actually handle the IRQs, though, we need to tell the kernel *where* the handlers are. */
/* A simple wrapper that adds a function pointer to the IRQ array. */ /* A simple wrapper that adds a function pointer to the IRQ array. */
size_t InstallIRQ(int IRQ, IRQHandler Handler) { void InstallIRQ(int IRQ, void (* Handler)(INTERRUPT_FRAME* Frame)) {
if (IRQ <= 32) { IRQ_Handlers[IRQ] = Handler;
Device::APIC::driver->Set(Core::GetCurrent()->ID, IRQ, 1);
IRQHandlerData* target = &IRQHandlers[IRQ];
if (target->numHandlers < 7) {
target->handlers[target->numHandlers] = Handler;
target->numHandlers++;
return target->numHandlers;
}
}
return 0;
} }
/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */ /* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */
void UninstallIRQHandler(int IRQ, size_t ID) { void UninstallIRQHandler(int IRQ) {
IRQHandlers[IRQ].handlers[ID] = NULL; // 0 is used in the common check to make sure that the function is callable. IRQ_Handlers[IRQ] = NULL; // 0 is used in the common check to make sure that the function is callable.
// This removes this IRQ from that check, ergo the function will no longer be called. // This removes this IRQ from that check, ergo the function will no longer be called.
} }
void EmptyIRQ(INTERRUPT_FRAME* frame) {
UNUSED(frame);
// Flash the borders green, then back to blue
SetForegroundColor(0x0000FF00);
for (size_t y = 0; y < bootldr.fb_height; y++) {
for (size_t x = 0; x < 20; x++) {
DrawPixel(x, y);
}
for (size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) {
DrawPixel(x, y);
}
}
for (size_t x = 0; x < bootldr.fb_width; x++) {
for (size_t y = 0; y < 20; y++) {
DrawPixel(x, y);
}
for (size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) {
DrawPixel(x, y);
}
}
for (size_t i = 0; i < 100000; i++) { }
SetForegroundColor(0x000000FF);
for (size_t y = 0; y < bootldr.fb_height; y++) {
for (size_t x = 0; x < 20; x++) {
DrawPixel(x, y);
}
for (size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) {
DrawPixel(x, y);
}
}
for (size_t x = 0; x < bootldr.fb_width; x++) {
for (size_t y = 0; y < 20; y++) {
DrawPixel(x, y);
}
for (size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) {
DrawPixel(x, y);
}
}
}
static void KeyboardCallback(INTERRUPT_FRAME* frame) {
UNUSED(frame);
uint8_t msg = ReadPort(0x60, 1);
UpdateKeyboard(msg);
WaitFor8042();
}
void InitInterrupts() { void InitInterrupts() {
size_t RFLAGS = ReadControlRegister('f'); size_t RFLAGS = ReadControlRegister('f');
@ -201,6 +239,11 @@ void InitInterrupts() {
WriteControlRegister('f', RFLAGS | (1 << 9)); WriteControlRegister('f', RFLAGS | (1 << 9));
} }
InstallIRQ(1, &KeyboardCallback);
Send8042(0xF002);
__asm__ __volatile__("sti"); __asm__ __volatile__("sti");
} }
@ -325,7 +368,7 @@ __attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t Erro
SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2)); SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2));
Core::GetCurrent()->StackTrace(10); Core::GetCurrent()->StackTrace(6);
ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault
} }

View File

@ -1,4 +1,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <kernel/system/memory.h> #include <kernel/system/memory.h>
#include <kernel/system/io.h> #include <kernel/system/io.h>
@ -7,6 +9,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/************************************************ /************************************************
* C O N S T A N T S A N D M A C R O S * C O N S T A N T S A N D M A C R O S
*************************************************/ *************************************************/
@ -132,6 +138,10 @@ static void BlockSetSize(block_header_t* Block, size_t Size) {
Block->Size = Size | (Block->Size & (BLOCK_FREE | BLOCK_PREV_FREE)); Block->Size = Size | (Block->Size & (BLOCK_FREE | BLOCK_PREV_FREE));
} }
static int BlockIsLast(const block_header_t* Block) {
return BlockSize(Block) == 0;
}
static int BlockIsFree(const block_header_t* Block) { static int BlockIsFree(const block_header_t* Block) {
return CAST(int, Block->Size & BLOCK_FREE); return CAST(int, Block->Size & BLOCK_FREE);
} }
@ -169,11 +179,13 @@ static block_header_t* OffsetToBlock(const void* Address, size_t Size) {
} }
static block_header_t* BlockGetPrevious(const block_header_t* Current) { static block_header_t* BlockGetPrevious(const block_header_t* Current) {
ASSERT(BlockPrevIsFree(Current), "BlockGetPrevious: Previous block NOT free");
return Current->LastBlock; return Current->LastBlock;
} }
static block_header_t* BlockGetNext(const block_header_t* Current) { static block_header_t* BlockGetNext(const block_header_t* Current) {
block_header_t* NextBlock = OffsetToBlock(WhereBlock(Current), BlockSize(Current) - BLOCK_OVERHEAD); block_header_t* NextBlock = OffsetToBlock(WhereBlock(Current), BlockSize(Current) - BLOCK_OVERHEAD);
ASSERT(!BlockIsLast(Current), "BlockGetNext: Current block is last!");
return NextBlock; return NextBlock;
} }
@ -200,17 +212,17 @@ static void BlockMarkUsed(block_header_t* Current) {
* P O I N T E R A L I G N M E N T F U N C T I O N S * P O I N T E R A L I G N M E N T F U N C T I O N S
************************************************************************************/ ************************************************************************************/
extern "C" size_t AlignUpwards(size_t Pointer, size_t Alignment) { size_t AlignUpwards(size_t Pointer, size_t Alignment) {
//ASSERT(((Alignment & (Alignment - 1)) == 0)); //ASSERT(((Alignment & (Alignment - 1)) == 0));
return (Pointer + (Alignment - 1)) & ~(Alignment - 1); return (Pointer + (Alignment - 1)) & ~(Alignment - 1);
} }
extern "C" size_t AlignDownwards(size_t Pointer, size_t Alignment) { size_t AlignDownwards(size_t Pointer, size_t Alignment) {
//ASSERT((Alignment & (Alignment - 1) == 0)); //ASSERT((Alignment & (Alignment - 1) == 0));
return (Pointer - (Pointer & (Alignment - 1))); return (Pointer - (Pointer & (Alignment - 1)));
} }
extern "C" void* AlignPointer(const void* Pointer, size_t Alignment) { void* AlignPointer(const void* Pointer, size_t Alignment) {
const ptrdiff_t AlignedPointer = const ptrdiff_t AlignedPointer =
(( ((
@ -218,6 +230,7 @@ extern "C" void* AlignPointer(const void* Pointer, size_t Alignment) {
+ (Alignment - 1)) + (Alignment - 1))
& ~(Alignment - 1) & ~(Alignment - 1)
); );
ASSERT(((Alignment & (Alignment - 1)) == 0), "AlignPointer: Requested alignment not aligned!");
return CAST(void*, AlignedPointer); return CAST(void*, AlignedPointer);
} }
@ -286,6 +299,8 @@ static block_header_t* FindSuitableBlock(allocator_control_t* Controller, int* F
SLMap = Controller->SecondLevel_Bitmap[FirstLevel]; SLMap = Controller->SecondLevel_Bitmap[FirstLevel];
} }
ASSERT(SLMap, "FindSuitableBlock: Second level bitmap not present!");
SecondLevel = Alloc_FindFirstOne(SLMap); SecondLevel = Alloc_FindFirstOne(SLMap);
*SecondLevelIndex = SecondLevel; *SecondLevelIndex = SecondLevel;
@ -296,6 +311,9 @@ static void RemoveFreeBlock(allocator_control_t* Controller, block_header_t* Blo
block_header_t* PreviousBlock = Block->LastFreeBlock; block_header_t* PreviousBlock = Block->LastFreeBlock;
block_header_t* NextBlock = Block->NextFreeBlock; block_header_t* NextBlock = Block->NextFreeBlock;
ASSERT(PreviousBlock, "RemoveFreeBlock: PreviousBlock is null!");
ASSERT(NextBlock, "RemoveFreeBlock: NextBlock is null!");
NextBlock->LastFreeBlock = PreviousBlock; NextBlock->LastFreeBlock = PreviousBlock;
PreviousBlock->NextFreeBlock = NextBlock; PreviousBlock->NextFreeBlock = NextBlock;
@ -316,6 +334,7 @@ static void
InsertFreeBlock(allocator_control_t* Controller, block_header_t* NewBlock, int FirstLevel, int SecondLevel) { InsertFreeBlock(allocator_control_t* Controller, block_header_t* NewBlock, int FirstLevel, int SecondLevel) {
block_header_t* Current = Controller->Blocks[FirstLevel][SecondLevel]; block_header_t* Current = Controller->Blocks[FirstLevel][SecondLevel];
ASSERT(Current, "InsertFreeBlock: Current Block is null!");
if (!Current) { if (!Current) {
SerialPrintf( SerialPrintf(
"Extra info: \r\n\tFirst Level: %x Second Level: %x\r\nFirst Level bitmap: %x, Second Level bitmap: %x\r\n\tBlocks %x, BlocksAddress: %x", "Extra info: \r\n\tFirst Level: %x Second Level: %x\r\nFirst Level bitmap: %x, Second Level bitmap: %x\r\n\tBlocks %x, BlocksAddress: %x",
@ -323,12 +342,16 @@ InsertFreeBlock(allocator_control_t* Controller, block_header_t* NewBlock, int F
Controller->Blocks, Controller->Blocks[FirstLevel][SecondLevel]); Controller->Blocks, Controller->Blocks[FirstLevel][SecondLevel]);
for (;;) { } for (;;) { }
} }
ASSERT(NewBlock, "InsertFreeBlock: New Block is null!");
NewBlock->NextFreeBlock = Current; NewBlock->NextFreeBlock = Current;
NewBlock->LastFreeBlock = &Controller->BlockNull; NewBlock->LastFreeBlock = &Controller->BlockNull;
Current->LastFreeBlock = NewBlock; Current->LastFreeBlock = NewBlock;
ASSERT(WhereBlock(NewBlock) == AlignPointer(WhereBlock(NewBlock), ALIGN_SIZE),
"InsertFreeBlock: Current block is not memory aligned!");
Controller->Blocks[FirstLevel][SecondLevel] = NewBlock; Controller->Blocks[FirstLevel][SecondLevel] = NewBlock;
Controller->FirstLevel_Bitmap |= (1U << FirstLevel); Controller->FirstLevel_Bitmap |= (1U << FirstLevel);
Controller->SecondLevel_Bitmap[FirstLevel] |= (1U << SecondLevel); Controller->SecondLevel_Bitmap[FirstLevel] |= (1U << SecondLevel);
@ -357,8 +380,15 @@ static block_header_t* SplitBlock(block_header_t* Block, size_t NewSize) {
const size_t RemainingSize = BlockSize(Block) - (NewSize + BLOCK_OVERHEAD); const size_t RemainingSize = BlockSize(Block) - (NewSize + BLOCK_OVERHEAD);
ASSERT(WhereBlock(Overlap) == AlignPointer(WhereBlock(Overlap), ALIGN_SIZE),
"SplitBlock: Requested size results in intermediary block which is not aligned!");
ASSERT(BlockSize(Block) == RemainingSize + NewSize + BLOCK_OVERHEAD, "SplitBlock: Maths error!");
BlockSetSize(Overlap, RemainingSize); BlockSetSize(Overlap, RemainingSize);
ASSERT(BlockSize(Overlap) >= BLOCK_MIN_SIZE, "SplitBlock: Requested size results in new block that is too small!");
BlockSetSize(Block, NewSize); BlockSetSize(Block, NewSize);
BlockMarkFree(Overlap); BlockMarkFree(Overlap);
@ -367,6 +397,7 @@ static block_header_t* SplitBlock(block_header_t* Block, size_t NewSize) {
} }
static block_header_t* MergeBlockDown(block_header_t* Previous, block_header_t* Block) { static block_header_t* MergeBlockDown(block_header_t* Previous, block_header_t* Block) {
ASSERT(!BlockIsLast(Previous), "MergeBlockDown: Previous block is the last block! (Current block is first block?)");
Previous->Size += BlockSize(Block) + BLOCK_OVERHEAD; Previous->Size += BlockSize(Block) + BLOCK_OVERHEAD;
BlockLinkToNext(Previous); BlockLinkToNext(Previous);
@ -377,6 +408,8 @@ static block_header_t* MergeEmptyBlockDown(allocator_control_t* Controller, bloc
if (BlockPrevIsFree(Block)) { if (BlockPrevIsFree(Block)) {
block_header_t* Previous = BlockGetPrevious(Block); block_header_t* Previous = BlockGetPrevious(Block);
ASSERT(Previous, "MergeEmptyBlockDown: Previous block is null!");
ASSERT(BlockIsFree(Previous), "MergeEmptyBlockDown: Previous block is free!");
RemoveBlock(Controller, Previous); RemoveBlock(Controller, Previous);
Block = MergeBlockDown(Previous, Block); Block = MergeBlockDown(Previous, Block);
} }
@ -386,8 +419,10 @@ static block_header_t* MergeEmptyBlockDown(allocator_control_t* Controller, bloc
static block_header_t* MergeNextBlockDown(allocator_control_t* Controller, block_header_t* Block) { static block_header_t* MergeNextBlockDown(allocator_control_t* Controller, block_header_t* Block) {
block_header_t* NextBlock = BlockGetNext(Block); block_header_t* NextBlock = BlockGetNext(Block);
ASSERT(NextBlock, "MergeNextBlockDown: Next Block is null!");
if (BlockIsFree(NextBlock)) { if (BlockIsFree(NextBlock)) {
ASSERT(!BlockIsLast(Block), "MergeNextBlockDown: Current block is the last block!");
RemoveBlock(Controller, NextBlock); RemoveBlock(Controller, NextBlock);
Block = MergeBlockDown(Block, NextBlock); Block = MergeBlockDown(Block, NextBlock);
} }
@ -396,6 +431,7 @@ static block_header_t* MergeNextBlockDown(allocator_control_t* Controller, block
} }
static void TrimBlockFree(allocator_control_t* Controller, block_header_t* Block, size_t Size) { static void TrimBlockFree(allocator_control_t* Controller, block_header_t* Block, size_t Size) {
ASSERT(BlockIsFree(Block), "TrimBlockFree: Current block is wholly free!");
if (CanBlockSplit(Block, Size)) { if (CanBlockSplit(Block, Size)) {
block_header_t* RemainingBlock = SplitBlock(Block, Size); block_header_t* RemainingBlock = SplitBlock(Block, Size);
@ -409,6 +445,8 @@ static void TrimBlockFree(allocator_control_t* Controller, block_header_t* Block
} }
static void TrimBlockUsed(allocator_control_t* Controller, block_header_t* Block, size_t Size) { static void TrimBlockUsed(allocator_control_t* Controller, block_header_t* Block, size_t Size) {
ASSERT(!BlockIsFree(Block), "TrimBlockUsed: The current block is wholly used!");
if (CanBlockSplit(Block, Size)) { if (CanBlockSplit(Block, Size)) {
block_header_t* RemainingBlock = SplitBlock(Block, Size); block_header_t* RemainingBlock = SplitBlock(Block, Size);
@ -454,6 +492,7 @@ static block_header_t* LocateFreeBlock(allocator_control_t* Controller, size_t S
} }
if (Block) { if (Block) {
ASSERT(BlockSize(Block) >= Size, "LocateFreeBlock: Found a block that is too small!");
RemoveFreeBlock(Controller, Block, FirstLevel, SecondLevel); RemoveFreeBlock(Controller, Block, FirstLevel, SecondLevel);
} }
@ -464,6 +503,7 @@ static void* PrepareUsedBlock(allocator_control_t* Controller, block_header_t* B
void* Pointer = 0; void* Pointer = 0;
if (Block) { if (Block) {
ASSERT(Size, "PrepareUsedBlock: Size is 0!");
TrimBlockFree(Controller, Block, Size); TrimBlockFree(Controller, Block, Size);
BlockMarkUsed(Block); BlockMarkUsed(Block);
Pointer = WhereBlock(Block); Pointer = WhereBlock(Block);
@ -576,6 +616,10 @@ void RemovePoolFromAllocator(allocator_t Allocator, mempool_t Pool) {
int FirstLevel = 0, SecondLevel = 0; int FirstLevel = 0, SecondLevel = 0;
ASSERT(BlockIsFree(Block), "RemovePoolFromAllocator: Current block is free!");
ASSERT(!BlockIsFree(BlockGetNext(Block)), "RemovePoolFromAllocator: Next Block is not free!");
ASSERT(BlockSize(BlockGetNext(Block)) == 0, "RemovePoolFromAllocator: Next block is size 0!");
RoundUpBlockSize(BlockSize(Block), &FirstLevel, &SecondLevel); RoundUpBlockSize(BlockSize(Block), &FirstLevel, &SecondLevel);
RemoveFreeBlock(Controller, Block, FirstLevel, SecondLevel); RemoveFreeBlock(Controller, Block, FirstLevel, SecondLevel);
} }
@ -658,6 +702,8 @@ void* AllocatorMalign(allocator_t Allocator, size_t Alignment, size_t Size) {
block_header_t* Block = LocateFreeBlock(Controller, AlignedSize); block_header_t* Block = LocateFreeBlock(Controller, AlignedSize);
ASSERT(sizeof(block_header_t) == BLOCK_MIN_SIZE + BLOCK_OVERHEAD, "AllocatorMalign: Maths error!");
if (Block) { if (Block) {
void* Address = WhereBlock(Block); void* Address = WhereBlock(Block);
void* AlignedAddress = AlignPointer(Address, Alignment); void* AlignedAddress = AlignPointer(Address, Alignment);
@ -675,6 +721,8 @@ void* AllocatorMalign(allocator_t Allocator, size_t Alignment, size_t Size) {
Gap = CAST(size_t, CAST(ptrdiff_t, AlignedAddress) - CAST(ptrdiff_t, Address)); Gap = CAST(size_t, CAST(ptrdiff_t, AlignedAddress) - CAST(ptrdiff_t, Address));
} }
ASSERT(Gap >= MinimumGap, "AllocatorMalign: Maths error 2!");
Block = TrimBlockLeadingFree(Controller, Block, Gap); Block = TrimBlockLeadingFree(Controller, Block, Gap);
} }
@ -687,6 +735,7 @@ void AllocatorFree(allocator_t Allocator, void* Address) {
if (Address) { if (Address) {
allocator_control_t* Controller = CAST(allocator_control_t*, Allocator); allocator_control_t* Controller = CAST(allocator_control_t*, Allocator);
block_header_t* Block = WhichBlock(Address); block_header_t* Block = WhichBlock(Address);
ASSERT(!BlockIsFree(Block), "AllocatorFree: Attempting to free a freed block!");
BlockMarkFree(Block); BlockMarkFree(Block);
Block = MergeEmptyBlockDown(Controller, Block); Block = MergeEmptyBlockDown(Controller, Block);
@ -731,6 +780,8 @@ void* AllocatorRealloc(allocator_t Allocator, void* Address, size_t NewSize) {
const size_t AdjustedSize = AlignRequestSize(NewSize, ALIGN_SIZE); const size_t AdjustedSize = AlignRequestSize(NewSize, ALIGN_SIZE);
ASSERT(!BlockIsFree(Block), "AllocatorRealloc: Requested block is not free!");
if (AdjustedSize > CurrentSize && (!BlockIsFree(NextBlock) || AdjustedSize > CombinedSize)) { if (AdjustedSize > CurrentSize && (!BlockIsFree(NextBlock) || AdjustedSize > CombinedSize)) {
// We're going to need more room // We're going to need more room
@ -753,3 +804,7 @@ void* AllocatorRealloc(allocator_t Allocator, void* Address, size_t NewSize) {
return Pointer; return Pointer;
} }
#ifdef __cplusplus
}
#endif

View File

@ -3,6 +3,10 @@
/** Durand's Amazing Super Duper Memory functions. */ /** Durand's Amazing Super Duper Memory functions. */
#ifdef __cplusplus
extern "C" {
#endif
#define VERSION "1.1" #define VERSION "1.1"
#define ALIGNMENT 16ul//4ul ///< This is the byte alignment that memory must be allocated on. IMPORTANT for GTK and other stuff. #define ALIGNMENT 16ul//4ul ///< This is the byte alignment that memory must be allocated on. IMPORTANT for GTK and other stuff.
@ -67,16 +71,16 @@ static int liballoc_free(void* ptr, size_t count) {
#define ALIGN(ptr) \ #define ALIGN(ptr) \
if ( ALIGNMENT > 1 ) \ if ( ALIGNMENT > 1 ) \
{ \ { \
uintptr_t ldiff; \ uintptr_t diff; \
ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \
ldiff = (uintptr_t)ptr & (ALIGNMENT-1); \ diff = (uintptr_t)ptr & (ALIGNMENT-1); \
if ( diff != 0 ) \ if ( diff != 0 ) \
{ \ { \
ldiff = ALIGNMENT - ldiff; \ diff = ALIGNMENT - diff; \
ptr = (void*)((uintptr_t)ptr + ldiff); \ ptr = (void*)((uintptr_t)ptr + diff); \
} \ } \
*((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \ *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \
ldiff + ALIGN_INFO; \ diff + ALIGN_INFO; \
} }
@ -810,6 +814,10 @@ void* PREFIX(realloc)(void* p, size_t size) {
return ptr; return ptr;
} }
#ifdef __cplusplus
}
#endif
void operator delete(void* addr, unsigned long __attribute__((unused)) size) { void operator delete(void* addr, unsigned long __attribute__((unused)) size) {
PREFIX(free)(addr); PREFIX(free)(addr);
} }

View File

@ -5,6 +5,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
#define PAGE_TABLES_GET_PDPT(address) \ #define PAGE_TABLES_GET_PDPT(address) \
(address & ((size_t) 0x1FF << 39)) >> 39 (address & ((size_t) 0x1FF << 39)) >> 39
#define PAGE_TABLES_GET_PDP(address) \ #define PAGE_TABLES_GET_PDP(address) \
@ -54,19 +58,6 @@ void InitPaging() {
MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS);
} }
SerialPrintf("[ Mem] Identity mapping the entire BIOS memory map.\r\n");
for (MMapEnt* MapEntry = &bootldr.mmap; (size_t) MapEntry < (size_t) &bootldr + bootldr.size; MapEntry++) {
size_t entry_from = MMapEnt_Ptr(MapEntry);
size_t entry_to = MMapEnt_Ptr(MapEntry) + MMapEnt_Size(MapEntry);
for (size_t i = entry_from; i < entry_to; i += PAGE_SIZE) {
MapVirtualPageNoDirect(&KernelAddressSpace, i, i, DEFAULT_PAGE_FLAGS);
MapVirtualPageNoDirect(&KernelAddressSpace, i, TO_DIRECT(i), DEFAULT_PAGE_FLAGS);
}
}
SerialPrintf("[ Mem] Identity mapping core system hardware.\r\n");
MapVirtualPageNoDirect(&KernelAddressSpace, APIC_REGION, APIC_REGION, DEFAULT_PAGE_FLAGS);
SerialPrintf("[ Mem] Mapping 0x%x bytes of bootloader structure, starting at 0x%p\r\n", bootldr.size, SerialPrintf("[ Mem] Mapping 0x%x bytes of bootloader structure, starting at 0x%p\r\n", bootldr.size,
BootldrAddress); BootldrAddress);
for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE) for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE)
@ -349,10 +340,6 @@ size_t* CreateNewPageTable(address_space_t* AddressSpace) {
return NewPML4; return NewPML4;
} }
void *operator new(size_t size) { #ifdef __cplusplus
return kmalloc(size);
}
void *operator new[](size_t size) {
return kmalloc(size);
} }
#endif

View File

@ -1,11 +1,16 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <lainlib/lainlib.h> #include <lainlib/lainlib.h>
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file contains functions for physical memory management. /* This file contains functions for physical memory management.
* *
* Physical Memory Management is performed with Buddy List allocators, which are one of the most performant systems available. * Physical Memory Management is performed with Buddy List allocators, which are one of the most performant systems available.
@ -16,9 +21,6 @@
* TODO: Document this mess. * TODO: Document this mess.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
#define MIN_ORDER 3 #define MIN_ORDER 3
#define PEEK(type, address) (*((volatile type*)(address))) #define PEEK(type, address) (*((volatile type*)(address)))
@ -172,7 +174,7 @@ void InitMemoryManager() {
MemoryPages = FreeMemorySize / PAGE_SIZE; MemoryPages = FreeMemorySize / PAGE_SIZE;
SerialPrintf("[ Mem] %u MB of usable memory detected, %u MB total.\r\n", (FreeMemorySize / 1024) / 1024, (FullMemorySize / 1024) / 1024); SerialPrintf("[ Mem] %u MB of memory detected.\r\n", (FreeMemorySize / 1024) / 1024);
} }

View File

@ -5,6 +5,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file contains functions for accessing the PCI bus, /* This file contains functions for accessing the PCI bus,
* and devices contained wherein. * and devices contained wherein.
* *
@ -747,3 +751,7 @@ const char* PCIGetClassName(uint8_t DeviceClass) {
return "Invalid device!"; return "Invalid device!";
} }
#ifdef __cplusplus
}
#endif

View File

@ -5,6 +5,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file serves to allow us to communicate with the computer through raw I/O. /* This file serves to allow us to communicate with the computer through raw I/O.
* It provides interfaces for Ports and commonly used Registers (Control Registers, Model-Specific Registers, GDT, IDT..) * It provides interfaces for Ports and commonly used Registers (Control Registers, Model-Specific Registers, GDT, IDT..)
* *
@ -253,3 +257,8 @@ void WriteTSR(uint16_t TSRData) {
__asm__ __volatile__("ltr %[src]" : : [src] "m"(TSRData) :); __asm__ __volatile__("ltr %[src]" : : [src] "m"(TSRData) :);
} }
#ifdef __cplusplus
}
#endif

View File

@ -4,6 +4,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file provides functions related to the Serial port. /* This file provides functions related to the Serial port.
* Through this file, you send and receive text and extra debugging information if available. * Through this file, you send and receive text and extra debugging information if available.
*/ */
@ -46,3 +50,7 @@ void WriteSerialString(const char* str, size_t len) {
WriteSerialChar(str[i]); WriteSerialChar(str[i]);
} }
} }
#ifdef __cplusplus
}
#endif

View File

@ -7,6 +7,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* This file contains all of the draw-to-screen routines. * This file contains all of the draw-to-screen routines.
* It (currently; 23/08/20) handles the keyboard input test routine, * It (currently; 23/08/20) handles the keyboard input test routine,
@ -474,3 +478,7 @@ void DrawFilledCircle(size_t centerX, size_t centerY, size_t radius) {
DrawVerticalLine(centerX, centerY - radius, 2 * radius + 1); DrawVerticalLine(centerX, centerY - radius, 2 * radius + 1);
DrawFilledCircleInternal(centerX, centerY, radius, 3, 0); DrawFilledCircleInternal(centerX, centerY, radius, 3, 0);
} }
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,10 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
#ifdef __cplusplus
extern "C" {
#endif
/* This file contains all of the String / Print related functions /* This file contains all of the String / Print related functions
* that are required by the core of the kernel. * that are required by the core of the kernel.
* *
@ -32,7 +36,7 @@ void NumToStr(char* Buffer, size_t Num, size_t Base) {
} }
extern "C" int SerialPrintf(const char* Format, ...) { int SerialPrintf(const char* Format, ...) {
va_list Parameters; va_list Parameters;
va_start(Parameters, Format); va_start(Parameters, Format);
@ -279,3 +283,7 @@ size_t ParseHexColor(const char* Stream, bool bgFlag) {
} }
return val; return val;
} }
#ifdef __cplusplus
}
#endif