Initial Commit
This commit is contained in:
+335
@@ -0,0 +1,335 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <limine.h>
|
||||
#include "video/render.h"
|
||||
#include "video/tga.h"
|
||||
#include "stdio.h"
|
||||
#include "arch/x86_64/gdt.h"
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include "arch/x86_64/isr.h"
|
||||
#include "arch/x86_64/irq.h"
|
||||
#include "mm/memory.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "arch/x86_64/ata.h"
|
||||
#include "fs/ext2.h"
|
||||
#include "string.h"
|
||||
#include "arch/x86_64/io.h"
|
||||
#include "arch/x86_64/usermode.h"
|
||||
#include "syscall/syscall.h"
|
||||
#include "fs/vfs.h"
|
||||
|
||||
uintptr_t g_hhdm_offset;
|
||||
#define CPU_STACK_SIZE (64 * 1024)
|
||||
|
||||
// Set the base revision to 6, this is recommended as this is the latest
|
||||
// base revision described by the Limine boot protocol specification.
|
||||
// See specification for further info.
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(6);
|
||||
|
||||
// The Limine requests can be placed anywhere, but it is important that
|
||||
// the compiler does not optimise them away, so, usually, they should
|
||||
// be made volatile or equivalent, _and_ they should be accessed at least
|
||||
// once or marked as used with the "used" attribute as done here.
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST_ID,
|
||||
.revision = 6
|
||||
};
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile struct limine_memmap_request memmap_request = {
|
||||
.id = LIMINE_MEMMAP_REQUEST_ID,
|
||||
.revision = 6
|
||||
};
|
||||
|
||||
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
volatile struct limine_stack_size_request stack_size_request = {
|
||||
.id = LIMINE_STACK_SIZE_REQUEST_ID,
|
||||
.revision = 0,
|
||||
.stack_size = CPU_STACK_SIZE,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Finally, define the start and end markers for the Limine requests.
|
||||
// These can also be moved anywhere, to any .c file, as seen fit.
|
||||
|
||||
__attribute__((used, section(".limine_requests_start")))
|
||||
static volatile uint64_t limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
|
||||
|
||||
__attribute__((used, section(".limine_requests_end")))
|
||||
static volatile uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
|
||||
|
||||
// GCC and Clang reserve the right to generate calls to the following
|
||||
// 4 functions even if they are not directly called.
|
||||
// Implement them as the C specification mandates.
|
||||
// DO NOT remove or rename these functions, or stuff will eventually break!
|
||||
// They CAN be moved to a different .c file.
|
||||
|
||||
|
||||
|
||||
// Halt and catch fire function.
|
||||
static void hcf(void) {
|
||||
for (;;) {
|
||||
asm volatile ("pause");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The following will be our kernel's entry point.
|
||||
// If renaming kmain() to something else, make sure to change the
|
||||
// linker script accordingly.
|
||||
void kmain(void) {
|
||||
// Ensure the bootloader actually understands our base revision (see spec).
|
||||
if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
||||
hcf();
|
||||
}
|
||||
|
||||
// Ensure we got a framebuffer.
|
||||
if (framebuffer_request.response == NULL
|
||||
|| framebuffer_request.response->framebuffer_count < 1) {
|
||||
hcf();
|
||||
}
|
||||
|
||||
// Fetch the first framebuffer.
|
||||
struct limine_framebuffer *framebuffer = framebuffer_request.response->framebuffers[0];
|
||||
|
||||
struct limine_memmap_response *memmap_response = memmap_request.response;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (!memmap_response) {
|
||||
hcf();
|
||||
}
|
||||
|
||||
|
||||
fb = framebuffer->address;
|
||||
fb_width = framebuffer->width;
|
||||
fb_height = framebuffer->height;
|
||||
fb_pitch = framebuffer->pitch / 4;
|
||||
|
||||
|
||||
printf("Hello, Kernel!\n");
|
||||
printf("Number: %d\n", 1234);
|
||||
printf("Hex: %x\n", 0xBEEF);
|
||||
|
||||
for (size_t i = 0; i < memmap_response->entry_count; i++) {
|
||||
struct limine_memmap_entry *entry = memmap_response->entries[i];
|
||||
|
||||
printf("Base: 0x%x%x, Length: 0x%x%x, Type: %d\n",
|
||||
(uint32_t)(entry->base >> 32), (uint32_t)entry->base,
|
||||
(uint32_t)(entry->length >> 32), (uint32_t)entry->length,
|
||||
entry->type);
|
||||
}
|
||||
x86_64_DisableInterrupts();
|
||||
|
||||
|
||||
|
||||
/*uint32_t msr_lo, msr_hi;
|
||||
asm volatile("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(0x1B));
|
||||
msr_lo &= ~(1 << 11);
|
||||
asm volatile("wrmsr" : : "a"(msr_lo), "d"(msr_hi), "c"(0x1B));*/
|
||||
printf("init pmm");
|
||||
pmm_init(memmap_response->entries, memmap_response->entry_count);
|
||||
printf("init slab");
|
||||
slab_init();
|
||||
printf("init vmm");
|
||||
vmm_init(memmap_response->entries, memmap_response->entry_count);
|
||||
printf("init gdt");
|
||||
x86_64_GDT_Initialize();
|
||||
x86_64_IDT_Initialize();
|
||||
x86_64_ISR_Initialize();
|
||||
x86_64_IRQ_Initialize();
|
||||
x86_64_EnableInterrupts();
|
||||
//lapic_timer_start(100);
|
||||
|
||||
ata_init();
|
||||
ata_identify();
|
||||
|
||||
if (!ext2_read_superblock()) {
|
||||
printf("EXT2 failed\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
if (!ext2_read_group_desc_table()) {
|
||||
printf("GDT failed\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
ext2_read_root_dir();
|
||||
printf("test");
|
||||
|
||||
|
||||
uint8_t* file_buffer = kmalloc(4096); // adjust if needed
|
||||
uint32_t file_size = 0;
|
||||
|
||||
if (ext2_read_file_from_root("a.txt", file_buffer, &file_size)) {
|
||||
printf("Read file (size %d):\n", file_size);
|
||||
|
||||
for (uint32_t i = 0; i < file_size; i++) {
|
||||
printf("%c", file_buffer[i]); // or printf("%c", ...)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Failed to read file\n");
|
||||
}
|
||||
|
||||
kfree(file_buffer);
|
||||
|
||||
uint8_t* file2_buffer = kmalloc(4096); // adjust if needed
|
||||
uint32_t file2_size = 0;
|
||||
|
||||
if (ext2_read_file_from_root("dogcatman.txt", file2_buffer, &file2_size)) {
|
||||
printf("Read file (size %d):\n", file2_size);
|
||||
|
||||
for (uint32_t i = 0; i < file2_size; i++) {
|
||||
printf("%c", file2_buffer[i]); // or printf("%c", ...)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Failed to read file\n");
|
||||
}
|
||||
|
||||
kfree(file2_buffer);
|
||||
|
||||
uint8_t* file3_buffer = kmalloc(4096); // adjust if needed
|
||||
uint32_t file3_size = 0;
|
||||
|
||||
if (ext2_read_file_from_root("test.txt", file3_buffer, &file3_size)) {
|
||||
printf("Read file (size %d):\n", file3_size);
|
||||
|
||||
for (uint32_t i = 0; i < file3_size; i++) {
|
||||
printf("%c", file3_buffer[i]); // or printf("%c", ...)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Failed to read file\n");
|
||||
}
|
||||
|
||||
kfree(file3_buffer);
|
||||
|
||||
uint8_t* file4_buffer = kmalloc(4096); // adjust if needed
|
||||
uint32_t file4_size = 0;
|
||||
|
||||
if (ext2_read_file_from_root("qwerty.txt", file4_buffer, &file4_size)) {
|
||||
printf("Read file (size %d):\n", file4_size);
|
||||
|
||||
for (uint32_t i = 0; i < file4_size; i++) {
|
||||
printf("%c", file4_buffer[i]); // or printf("%c", ...)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Failed to read file\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
kfree(file4_buffer);
|
||||
|
||||
const char* msg = "hello i wrote from kernel!";
|
||||
|
||||
ext2_write_file_from_root("qwerty.txt", (const uint8_t*)msg, strlen(msg), EXT2_WRITE_APPEND);
|
||||
|
||||
uint8_t* file5_buffer = kmalloc(4096); // adjust if needed
|
||||
uint32_t file5_size = 0;
|
||||
|
||||
if (ext2_read_file_from_root("qwerty.txt", file5_buffer, &file5_size)) {
|
||||
printf("Read file (size %d):\n", file5_size);
|
||||
|
||||
for (uint32_t i = 0; i < file5_size; i++) {
|
||||
printf("%c", file5_buffer[i]); // or printf("%c", ...)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Failed to read file\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
kfree(file5_buffer);
|
||||
|
||||
uint32_t inum = ext2_resolve_path("charlie.tga");
|
||||
if (!inum) {
|
||||
printf("file not found\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
ext2_inode_t inode;
|
||||
if (!ext2_read_inode(inum, &inode)) {
|
||||
printf("inode read failed\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
uint32_t tga_size = inode.i_size;
|
||||
if (!tga_size) {
|
||||
printf("tga file is empty\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
uint8_t *file_buf = kmalloc(tga_size);
|
||||
if (!file_buf) {
|
||||
printf("OOM allocating tga buffer (%u bytes)\n", tga_size);
|
||||
hcf();
|
||||
}
|
||||
|
||||
if (!ext2_read_file(&inode, file_buf)) {
|
||||
printf("read failed\n");
|
||||
kfree(file_buf);
|
||||
hcf();
|
||||
}
|
||||
|
||||
uint32_t *img = tga_parse(file_buf, tga_size);
|
||||
kfree(file_buf); // free the raw file buffer as soon as parse is done
|
||||
|
||||
if (!img) {
|
||||
printf("tga parse failed\n");
|
||||
hcf();
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int new_w = img[0] * 5;
|
||||
int new_h = img[1] * 5;
|
||||
clear_screen(0xFF1E1E1E);
|
||||
draw_image_bilinear(img, x, y, new_w, new_h);
|
||||
kfree(img);
|
||||
|
||||
//clear_screen(0xFF1E1E1E);
|
||||
|
||||
fd_t fd = VFS_Open("/a.txt");
|
||||
if (fd < 0) {
|
||||
printf("asudg");
|
||||
}
|
||||
uint8_t buf[128];
|
||||
int n;
|
||||
|
||||
while ((n = VFS_Read(fd, buf, sizeof(buf))) > 0)
|
||||
{
|
||||
VFS_Write(VFS_FD_STDOUT, buf, n);
|
||||
}
|
||||
|
||||
VFS_Close(fd);
|
||||
|
||||
x86_64_EnableInterrupts();
|
||||
syscall_init();
|
||||
start_userspace();
|
||||
printf("tst");
|
||||
|
||||
// We're done, just hang...
|
||||
hcf();
|
||||
}
|
||||
Reference in New Issue
Block a user