Start isolating processes
Kernel moved to a fixed range high in address space. Memory allocation now happens per process. Single kernel process added.
This commit is contained in:
+6
-6
@@ -10,7 +10,7 @@ void cat(process_t *proc, uint8_t argc, char **argv) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_t *path = path_open(proc->root, proc->cwd, argv[1]);
|
path_t *path = path_open(proc, proc->cwd, argv[1]);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
WRITE_S("cat: invalid path\n");
|
WRITE_S("cat: invalid path\n");
|
||||||
return;
|
return;
|
||||||
@@ -19,13 +19,13 @@ void cat(process_t *proc, uint8_t argc, char **argv) {
|
|||||||
fs_node_t *curr = path->depth ? path->stack[path->depth - 1] : proc->root;
|
fs_node_t *curr = path->depth ? path->stack[path->depth - 1] : proc->root;
|
||||||
if (curr->is_dir) {
|
if (curr->is_dir) {
|
||||||
WRITE_S("cat: can not print a directory\n");
|
WRITE_S("cat: can not print a directory\n");
|
||||||
path_close(path);
|
path_close(proc, path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *content = memory_allocate(curr->size + 1);
|
char *content = memory_allocate(proc, curr->size + 1);
|
||||||
fs_read(curr, 0, curr->size, content);
|
fs_read(proc, curr, 0, curr->size, content);
|
||||||
proc->stdout->write(proc->stdout, content, curr->size);
|
proc->stdout->write(proc->stdout, content, curr->size);
|
||||||
memory_free(content);
|
memory_free(proc, content);
|
||||||
path_close(path);
|
path_close(proc, path);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -9,7 +9,7 @@ void ls(process_t *proc, uint8_t argc, char **argv) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_t *path = path_open(proc->root, proc->cwd, argc == 1 ? "." : argv[1]);
|
path_t *path = path_open(proc, proc->cwd, argc == 1 ? "." : argv[1]);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
WRITE_S("ls: invalid path\n");
|
WRITE_S("ls: invalid path\n");
|
||||||
return;
|
return;
|
||||||
@@ -18,17 +18,17 @@ void ls(process_t *proc, uint8_t argc, char **argv) {
|
|||||||
fs_node_t *curr = path->depth ? path->stack[path->depth - 1] : proc->root;
|
fs_node_t *curr = path->depth ? path->stack[path->depth - 1] : proc->root;
|
||||||
if (!curr->is_dir) {
|
if (!curr->is_dir) {
|
||||||
WRITE_S("ls: can not list a file\n");
|
WRITE_S("ls: can not list a file\n");
|
||||||
path_close(path);
|
path_close(proc, path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t j = 0;
|
uint8_t j = 0;
|
||||||
fs_node_t *item = fs_open_at(curr, j++);
|
fs_node_t *item = fs_open_at(proc, curr, j++);
|
||||||
while (item) {
|
while (item) {
|
||||||
WRITE_D(item->name);
|
WRITE_D(item->name);
|
||||||
WRITE_S("\n");
|
WRITE_S("\n");
|
||||||
fs_close(item);
|
fs_close(proc, item);
|
||||||
item = fs_open_at(curr, j++);
|
item = fs_open_at(proc, curr, j++);
|
||||||
}
|
}
|
||||||
path_close(path);
|
path_close(proc, path);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -56,13 +56,13 @@ static void cd(process_t *proc, uint8_t argc, char **argv) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_t *new = path_open(proc->root, proc->cwd, argv[1]);
|
path_t *new = path_open(proc, proc->cwd, argv[1]);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
WRITE_S("cd: path does not exist\n");
|
WRITE_S("cd: path does not exist\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_close(proc->cwd);
|
path_close(proc, proc->cwd);
|
||||||
proc->cwd = new;
|
proc->cwd = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,9 +270,7 @@ void terminal(process_t *p, __attribute__((unused)) uint8_t argc, __attribute__(
|
|||||||
|
|
||||||
proc = p;
|
proc = p;
|
||||||
|
|
||||||
char *greeting = string_format("Welcome to FreywarOS v%s!\n\n", VERSION);
|
WRITE_D("Welcome to FreywarOS v" VERSION "!\n\n");
|
||||||
WRITE_D(greeting);
|
|
||||||
memory_free(greeting);
|
|
||||||
|
|
||||||
print_prompt();
|
print_prompt();
|
||||||
|
|
||||||
|
|||||||
+14
-7
@@ -276,23 +276,30 @@ protected_mode:
|
|||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov esp, 0x00090000
|
mov esp, 0x00090000
|
||||||
|
|
||||||
; zero page table memory at 0x00010000 (3 pages = 768 dwords)
|
; zero page table memory at 0x00010000
|
||||||
mov edi, 0x00010000
|
mov edi, 0x00010000
|
||||||
mov ecx, 768
|
mov ecx, 256 * 5
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
; PML4[0] -> PDPT at 0x00011000
|
; PML4[0] -> PDPT at 0x00011000
|
||||||
mov dword [0x00010000], 0x00011003
|
mov dword [0x00010000], 0x00011003
|
||||||
; PDPT[0] -> PD at 0x00012000
|
; PML4[511] -> PDPT at 0x00012000
|
||||||
mov dword [0x00011000], 0x00012003
|
mov dword [0x00010FF8], 0x00012003
|
||||||
|
; PML4[0].PDPT[0] -> PD at 0x00013000
|
||||||
|
mov dword [0x00011000], 0x00013003
|
||||||
|
; PML4[511].PDPT[510] -> PD at 0x00014000
|
||||||
|
mov dword [0x00012FF0], 0x00014003
|
||||||
; PD: fill 64 entries, each mapping 2MB
|
; PD: fill 64 entries, each mapping 2MB
|
||||||
mov edi, 0x00012000
|
mov edi, 0x00013000
|
||||||
mov eax, 0x00000083 ; present, writable, huge page, base 0
|
mov eax, 0x00000083 ; present, writable, huge page, base 0
|
||||||
mov ecx, 64
|
mov ecx, 64
|
||||||
|
|
||||||
.fill_pd:
|
.fill_pd:
|
||||||
|
mov ebx, edi
|
||||||
|
add ebx, 0x1000
|
||||||
mov dword [edi], eax
|
mov dword [edi], eax
|
||||||
|
mov dword [ebx], eax
|
||||||
add edi, 8
|
add edi, 8
|
||||||
add eax, 0x00200000 ; next 2MB
|
add eax, 0x00200000 ; next 2MB
|
||||||
loop .fill_pd
|
loop .fill_pd
|
||||||
@@ -327,11 +334,11 @@ long_mode:
|
|||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov rsp, 0x0000000000090000
|
mov rsp, 0xFFFFFFFF80090000
|
||||||
|
|
||||||
xor rax, rax
|
xor rax, rax
|
||||||
xor rbx, rbx
|
xor rbx, rbx
|
||||||
xor rcx, rcx
|
xor rcx, rcx
|
||||||
xor rdx, rdx
|
xor rdx, rdx
|
||||||
|
|
||||||
jmp 0x00020000
|
jmp 0xFFFFFFFF80020000
|
||||||
|
|||||||
+30
-31
@@ -1,10 +1,9 @@
|
|||||||
#include "src/fat16.h"
|
#include "src/fat16.h"
|
||||||
#include "src/ata.h"
|
#include "src/ata.h"
|
||||||
#include "src/fs.h"
|
|
||||||
#include "src/memory.h"
|
#include "src/memory.h"
|
||||||
|
#include "src/process.h"
|
||||||
#include "src/string.h"
|
#include "src/string.h"
|
||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
#define FIRST_PARTITION_SECTOR 2048
|
#define FIRST_PARTITION_SECTOR 2048
|
||||||
@@ -74,11 +73,11 @@ static void from_8_3(const char *name, const char *extension, char *output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_mount() { // Assuming one partition.
|
fs_node_t *fat16_mount(process_t *kernel) { // Assuming one partition.
|
||||||
uint8_t sector[512];
|
uint8_t sector[512];
|
||||||
ata_read_sectors(FIRST_PARTITION_SECTOR, 1, §or);
|
ata_read_sectors(FIRST_PARTITION_SECTOR, 1, §or);
|
||||||
memory_copy(sector + 11, sizeof(fat16_bpb_t), &bpb);
|
memory_copy(sector + 11, sizeof(fat16_bpb_t), &bpb);
|
||||||
fat16_node_t *node = memory_allocate(sizeof(fat16_node_t));
|
fat16_node_t *node = memory_allocate(kernel, sizeof(fat16_node_t));
|
||||||
node->base.type = FAT16;
|
node->base.type = FAT16;
|
||||||
node->base.name[0] = node->entry.name[0] = '/';
|
node->base.name[0] = node->entry.name[0] = '/';
|
||||||
node->base.size = node->entry.size = sizeof(fat16_dir_entry_t) * bpb.root_entry_count;
|
node->base.size = node->entry.size = sizeof(fat16_dir_entry_t) * bpb.root_entry_count;
|
||||||
@@ -86,23 +85,23 @@ fs_node_t *fat16_mount() { // Assuming one partition.
|
|||||||
return fs = (fs_node_t *)node;
|
return fs = (fs_node_t *)node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ensure_fat() {
|
static void ensure_fat(process_t *proc) {
|
||||||
ASSERT(bpb.sectors_per_fat < 256, "ensure_fat: big FAT not implemented")
|
ASSERT(bpb.sectors_per_fat < 256, "ensure_fat: big FAT not implemented")
|
||||||
if (!fat) {
|
if (!fat) {
|
||||||
fat = memory_allocate(bpb.sectors_per_fat * SECTOR_SIZE);
|
fat = memory_allocate(proc->kernel, bpb.sectors_per_fat * SECTOR_SIZE);
|
||||||
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat);
|
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fat16_dir_entry_t *load_directory(fat16_node_t *directory) {
|
static fat16_dir_entry_t *load_directory(process_t *proc, fat16_node_t *directory) {
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
|
|
||||||
if (!directory->entry.first_cluster) {
|
if (!directory->entry.first_cluster) {
|
||||||
uint8_t sectors = (uint8_t)((directory->base.size + SECTOR_SIZE - 1) / SECTOR_SIZE);
|
uint8_t sectors = (uint8_t)((directory->base.size + SECTOR_SIZE - 1) / SECTOR_SIZE);
|
||||||
entries = memory_allocate(sectors * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
entries = memory_allocate(proc, sectors * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
||||||
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, entries);
|
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, entries);
|
||||||
} else {
|
} else {
|
||||||
ensure_fat();
|
ensure_fat(proc);
|
||||||
|
|
||||||
uint16_t next_cluster = directory->entry.first_cluster;
|
uint16_t next_cluster = directory->entry.first_cluster;
|
||||||
uint32_t cluster_count = 0;
|
uint32_t cluster_count = 0;
|
||||||
@@ -110,8 +109,8 @@ static fat16_dir_entry_t *load_directory(fat16_node_t *directory) {
|
|||||||
cluster_count++;
|
cluster_count++;
|
||||||
next_cluster = fat[next_cluster];
|
next_cluster = fat[next_cluster];
|
||||||
}
|
}
|
||||||
entries =
|
entries = memory_allocate(proc, cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE +
|
||||||
memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
||||||
|
|
||||||
uint8_t *chunk = (uint8_t *)entries;
|
uint8_t *chunk = (uint8_t *)entries;
|
||||||
next_cluster = directory->entry.first_cluster;
|
next_cluster = directory->entry.first_cluster;
|
||||||
@@ -128,12 +127,12 @@ static fat16_dir_entry_t *load_directory(fat16_node_t *directory) {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fs_node_t *open_entry(const char *name, const fat16_dir_entry_t *entry) {
|
static fs_node_t *open_entry(process_t *proc, const char *name, const fat16_dir_entry_t *entry) {
|
||||||
if (!entry->name[0]) {
|
if (!entry->name[0]) {
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fat16_node_t *result = memory_allocate(sizeof(fat16_node_t));
|
fat16_node_t *result = memory_allocate(proc, sizeof(fat16_node_t));
|
||||||
memory_copy((char *)name, string_length(name) + 1, &(result->base.name));
|
memory_copy((char *)name, string_length(name) + 1, &(result->base.name));
|
||||||
result->base.type = FAT16;
|
result->base.type = FAT16;
|
||||||
result->base.size = entry->size;
|
result->base.size = entry->size;
|
||||||
@@ -143,14 +142,14 @@ static fs_node_t *open_entry(const char *name, const fat16_dir_entry_t *entry) {
|
|||||||
return (fs_node_t *)result;
|
return (fs_node_t *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) {
|
fs_node_t *fat16_open_by(process_t *proc, const fs_node_t *directory, const char *name) {
|
||||||
ASSERT(directory->type == FAT16, "fat16_open_by: directory is not FAT16");
|
ASSERT(directory->type == FAT16, "fat16_open_by: directory is not FAT16");
|
||||||
ASSERT(directory->is_dir, "fat16_open_by: directory is not a directory");
|
ASSERT(directory->is_dir, "fat16_open_by: directory is not a directory");
|
||||||
|
|
||||||
char name_8_3[12];
|
char name_8_3[12];
|
||||||
to_8_3(name, name_8_3);
|
to_8_3(name, name_8_3);
|
||||||
|
|
||||||
fat16_dir_entry_t *entries = load_directory((fat16_node_t *)directory);
|
fat16_dir_entry_t *entries = load_directory(proc, (fat16_node_t *)directory);
|
||||||
|
|
||||||
fat16_dir_entry_t *entry = entries;
|
fat16_dir_entry_t *entry = entries;
|
||||||
while (entry->name[0]) {
|
while (entry->name[0]) {
|
||||||
@@ -160,16 +159,16 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) {
|
|||||||
entry++;
|
entry++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *result = open_entry(name, entry);
|
fs_node_t *result = open_entry(proc, name, entry);
|
||||||
memory_free(entries);
|
memory_free(proc, entries);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index) {
|
fs_node_t *fat16_open_at(process_t *proc, const fs_node_t *directory, uint64_t index) {
|
||||||
ASSERT(directory->type == FAT16, "fat16_open_at: directory is not FAT16");
|
ASSERT(directory->type == FAT16, "fat16_open_at: directory is not FAT16");
|
||||||
ASSERT(directory->is_dir, "fat16_open_at: directory is not a directory");
|
ASSERT(directory->is_dir, "fat16_open_at: directory is not a directory");
|
||||||
|
|
||||||
fat16_dir_entry_t *entries = load_directory((fat16_node_t *)directory);
|
fat16_dir_entry_t *entries = load_directory(proc, (fat16_node_t *)directory);
|
||||||
|
|
||||||
uint64_t ei = 0, vi = 0;
|
uint64_t ei = 0, vi = 0;
|
||||||
while (entries[ei].name[0]) {
|
while (entries[ei].name[0]) {
|
||||||
@@ -189,23 +188,23 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index) {
|
|||||||
char name[13];
|
char name[13];
|
||||||
from_8_3(entries[ei].name, entries[ei].ext, name);
|
from_8_3(entries[ei].name, entries[ei].ext, name);
|
||||||
|
|
||||||
fs_node_t *result = open_entry(name, entries + ei);
|
fs_node_t *result = open_entry(proc, name, entries + ei);
|
||||||
memory_free(entries);
|
memory_free(proc, entries);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_again(const fs_node_t *source) {
|
fs_node_t *fat16_open_again(process_t *proc, const fs_node_t *source) {
|
||||||
fs_node_t *result = memory_allocate(sizeof(fat16_node_t));
|
fs_node_t *result = memory_allocate(proc, sizeof(fat16_node_t));
|
||||||
memory_copy(source, sizeof(fat16_node_t), result);
|
memory_copy(source, sizeof(fat16_node_t), result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
void fat16_read(process_t *proc, const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
||||||
ASSERT(file->type == FAT16, "fat16_read: file is not FAT16");
|
ASSERT(file->type == FAT16, "fat16_read: file is not FAT16");
|
||||||
ASSERT(!file->is_dir, "fat16_read: can not read directory");
|
ASSERT(!file->is_dir, "fat16_read: can not read directory");
|
||||||
ASSERT(file->size >= offset + size, "fat16_read: offset/size are out of bounds");
|
ASSERT(file->size >= offset + size, "fat16_read: offset/size are out of bounds");
|
||||||
|
|
||||||
ensure_fat();
|
ensure_fat(proc);
|
||||||
|
|
||||||
fat16_node_t *fat_file = (fat16_node_t *)file;
|
fat16_node_t *fat_file = (fat16_node_t *)file;
|
||||||
|
|
||||||
@@ -221,7 +220,7 @@ void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to)
|
|||||||
|
|
||||||
uint8_t *cursor = to;
|
uint8_t *cursor = to;
|
||||||
|
|
||||||
uint8_t *tmp = memory_allocate(cluster_size);
|
uint8_t *tmp = memory_allocate(proc, cluster_size);
|
||||||
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.sectors_per_fat * bpb.fats_count +
|
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.sectors_per_fat * bpb.fats_count +
|
||||||
(bpb.root_entry_count * sizeof(fat16_dir_entry_t) + SECTOR_SIZE - 1) / SECTOR_SIZE +
|
(bpb.root_entry_count * sizeof(fat16_dir_entry_t) + SECTOR_SIZE - 1) / SECTOR_SIZE +
|
||||||
bpb.sectors_per_cluster * (next_cluster - 2),
|
bpb.sectors_per_cluster * (next_cluster - 2),
|
||||||
@@ -250,18 +249,18 @@ void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to)
|
|||||||
memory_copy(tmp, size, cursor);
|
memory_copy(tmp, size, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_free(tmp);
|
memory_free(proc, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fat16_close(fs_node_t *node) {
|
void fat16_close(process_t *proc, fs_node_t *node) {
|
||||||
ASSERT(node->type == FAT16, "fat16_close: node is not FAT16");
|
ASSERT(node->type == FAT16, "fat16_close: node is not FAT16");
|
||||||
ASSERT(node != fs, "fat16_close: can not unmount FS");
|
ASSERT(node != fs, "fat16_close: can not unmount FS");
|
||||||
memory_free(node);
|
memory_free(proc, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fat16_unmount(fs_node_t *node) {
|
void fat16_unmount(process_t *kernel, fs_node_t *node) {
|
||||||
ASSERT(node->type == FAT16, "fat16_unmount: node is not FAT16");
|
ASSERT(node->type == FAT16, "fat16_unmount: node is not FAT16");
|
||||||
ASSERT(node == fs, "fat16_unmount: node is not filesystem");
|
ASSERT(node == fs, "fat16_unmount: node is not filesystem");
|
||||||
memory_free(node);
|
memory_free(kernel, node);
|
||||||
fs = NUL;
|
fs = NUL;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
#include "src/fs.h"
|
#include "src/fs.h"
|
||||||
|
|
||||||
|
typedef struct process process_t;
|
||||||
|
|
||||||
#define FAT16 1
|
#define FAT16 1
|
||||||
|
|
||||||
fs_node_t *fat16_mount();
|
fs_node_t *fat16_mount(process_t *kernel);
|
||||||
|
|
||||||
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name);
|
fs_node_t *fat16_open_by(process_t *proc, const fs_node_t *directory, const char *name);
|
||||||
|
|
||||||
fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index);
|
fs_node_t *fat16_open_at(process_t *proc, const fs_node_t *directory, uint64_t index);
|
||||||
|
|
||||||
fs_node_t *fat16_open_again(const fs_node_t *source);
|
fs_node_t *fat16_open_again(process_t *proc, const fs_node_t *source);
|
||||||
|
|
||||||
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
void fat16_read(process_t *proc, const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
||||||
|
|
||||||
void fat16_close(fs_node_t *node);
|
void fat16_close(process_t *proc, fs_node_t *node);
|
||||||
|
|
||||||
void fat16_unmount(fs_node_t *fs);
|
void fat16_unmount(process_t *kernel, fs_node_t *fs);
|
||||||
|
|||||||
@@ -1,30 +1,31 @@
|
|||||||
#include "src/fs.h"
|
#include "src/fs.h"
|
||||||
#include "src/fat16.h"
|
#include "src/fat16.h"
|
||||||
|
#include "src/process.h"
|
||||||
|
|
||||||
fs_node_t *fs_mount() {
|
fs_node_t *fs_mount(process_t *kernel) {
|
||||||
return fat16_mount();
|
return fat16_mount(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name) {
|
fs_node_t *fs_open_by(process_t *proc, const fs_node_t *directory, const char *name) {
|
||||||
return fat16_open_by(directory, name);
|
return fat16_open_by(proc, directory, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index) {
|
fs_node_t *fs_open_at(process_t *proc, const fs_node_t *directory, uint64_t index) {
|
||||||
return fat16_open_at(directory, index);
|
return fat16_open_at(proc, directory, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_again(const fs_node_t *source) {
|
fs_node_t *fs_open_again(process_t *proc, const fs_node_t *source) {
|
||||||
return fat16_open_again(source);
|
return fat16_open_again(proc, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
void fs_read(process_t *proc, const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
||||||
fat16_read(file, offset, size, to);
|
fat16_read(proc, file, offset, size, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_close(fs_node_t *node) {
|
void fs_close(process_t *proc, fs_node_t *node) {
|
||||||
fat16_close(node);
|
fat16_close(proc, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_unmount(fs_node_t *fs) {
|
void fs_unmount(process_t *kernel, fs_node_t *fs) {
|
||||||
fat16_unmount(fs);
|
fat16_unmount(kernel, fs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#define FILENAME_SIZE_LIMIT 255
|
#define FILENAME_SIZE_LIMIT 255
|
||||||
|
|
||||||
|
typedef struct process process_t;
|
||||||
|
|
||||||
typedef struct fs_node {
|
typedef struct fs_node {
|
||||||
char name[FILENAME_SIZE_LIMIT + 1];
|
char name[FILENAME_SIZE_LIMIT + 1];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@@ -12,16 +14,16 @@ typedef struct fs_node {
|
|||||||
} fs_node_t;
|
} fs_node_t;
|
||||||
|
|
||||||
|
|
||||||
fs_node_t *fs_mount();
|
fs_node_t *fs_mount(process_t *kernel);
|
||||||
|
|
||||||
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name);
|
fs_node_t *fs_open_by(process_t *proc, const fs_node_t *directory, const char *name);
|
||||||
|
|
||||||
fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index);
|
fs_node_t *fs_open_at(process_t *proc, const fs_node_t *directory, uint64_t index);
|
||||||
|
|
||||||
fs_node_t *fs_open_again(const fs_node_t *source);
|
fs_node_t *fs_open_again(process_t *proc, const fs_node_t *source);
|
||||||
|
|
||||||
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
void fs_read(process_t *proc, const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
||||||
|
|
||||||
void fs_close(fs_node_t *node);
|
void fs_close(process_t *proc, fs_node_t *node);
|
||||||
|
|
||||||
void fs_unmount(fs_node_t *fs);
|
void fs_unmount(process_t *kernel, fs_node_t *fs);
|
||||||
|
|||||||
+9
-7
@@ -32,6 +32,8 @@ __attribute__((interrupt)) void isr_ata_primary(__attribute__((unused)) struct i
|
|||||||
outb(0xA0, 0x20);
|
outb(0xA0, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static process_t kernel_process;
|
||||||
|
|
||||||
void kernel_main() {
|
void kernel_main() {
|
||||||
pic_init();
|
pic_init();
|
||||||
idt_init();
|
idt_init();
|
||||||
@@ -42,15 +44,15 @@ void kernel_main() {
|
|||||||
idt_set_entry(46, isr_ata_primary, 0x8E);
|
idt_set_entry(46, isr_ata_primary, 0x8E);
|
||||||
__asm__ volatile("sti");
|
__asm__ volatile("sti");
|
||||||
|
|
||||||
memory_init();
|
memory_init(&kernel_process);
|
||||||
|
kernel_process.root = fs_mount(&kernel_process);
|
||||||
|
kernel_process.cwd = memory_allocate(&kernel_process, sizeof(path_t));
|
||||||
|
kernel_process.stdin = keyboard_init();
|
||||||
|
kernel_process.stdout = vga_init();
|
||||||
|
|
||||||
process_t *proc = memory_allocate(sizeof(process_t));
|
terminal(&kernel_process, 0, NUL);
|
||||||
proc->cwd = memory_allocate(sizeof(path_t));
|
|
||||||
proc->root = fs_mount();
|
|
||||||
proc->stdin = keyboard_init();
|
|
||||||
proc->stdout = vga_init();
|
|
||||||
|
|
||||||
terminal(proc, 0, NUL);
|
fs_unmount(&kernel_process, kernel_process.root);
|
||||||
|
|
||||||
outw(0x604, 0x2000); // TODO: parse ACPI tables for real hardware
|
outw(0x604, 0x2000); // TODO: parse ACPI tables for real hardware
|
||||||
__asm__ volatile("cli; hlt");
|
__asm__ volatile("cli; hlt");
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
ENTRY(kernel_main)
|
ENTRY(kernel_main)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0x0000000000020000;
|
. = 0xFFFFFFFF80020000;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text)
|
*(.text)
|
||||||
|
|||||||
+18
-20
@@ -1,9 +1,9 @@
|
|||||||
#include "src/memory.h"
|
#include "src/memory.h"
|
||||||
#include "src/panic.h"
|
#include "src/panic.h"
|
||||||
|
#include "src/process.h"
|
||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define MEMORY_SIZE 134217728
|
#define MEMORY_SIZE 0x08000000
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE)
|
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE)
|
||||||
#define MAP_UNIT 64
|
#define MAP_UNIT 64
|
||||||
@@ -49,29 +49,27 @@ __attribute__((unused)) static void memory_page_free(void *address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define KERNEL_VIRTUAL_BASE 0xFFFFFFFF80000000ULL
|
||||||
|
#define PHYS_TO_VIRT(phys) ((void *)((uint64_t)(phys) + KERNEL_VIRTUAL_BASE))
|
||||||
|
#define VIRT_TO_PHYS(virt) ((uint64_t)(virt) - KERNEL_VIRTUAL_BASE)
|
||||||
#define HEAP_PAGE_COUNT 256
|
#define HEAP_PAGE_COUNT 256
|
||||||
|
|
||||||
typedef struct free_chunk {
|
void memory_init(process_t *kernel) {
|
||||||
uint64_t size; // header + data
|
kernel->pml4 = PHYS_TO_VIRT(0x00010000);
|
||||||
struct free_chunk *next;
|
// Assumes 0x0 -> KERNEL_VIRTUAL_BASE mapping and `memory_page_allocate` issuing continuous pages initially.
|
||||||
} free_chunk_t;
|
kernel->heap = PHYS_TO_VIRT(memory_page_allocate());
|
||||||
|
|
||||||
static free_chunk_t *free_list;
|
|
||||||
|
|
||||||
void memory_init() {
|
|
||||||
free_list = memory_page_allocate();
|
|
||||||
for (uint64_t i = 1; i < HEAP_PAGE_COUNT; i++) {
|
for (uint64_t i = 1; i < HEAP_PAGE_COUNT; i++) {
|
||||||
memory_page_allocate(); // TODO Map the pages.
|
memory_page_allocate();
|
||||||
}
|
}
|
||||||
free_list->size = HEAP_PAGE_COUNT * PAGE_SIZE;
|
kernel->heap->size = HEAP_PAGE_COUNT * PAGE_SIZE;
|
||||||
free_list->next = NUL;
|
kernel->heap->next = NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memory_allocate(uint64_t size) {
|
void *memory_allocate(process_t *proc, uint64_t size) {
|
||||||
size = sizeof(free_chunk_t) + (size + 7) & (uint64_t)~7;
|
size = sizeof(free_chunk_t) + (size + 7) & (uint64_t)~7;
|
||||||
|
|
||||||
free_chunk_t *prev = NUL;
|
free_chunk_t *prev = NUL;
|
||||||
free_chunk_t *curr = free_list;
|
free_chunk_t *curr = proc->heap;
|
||||||
|
|
||||||
while (curr) {
|
while (curr) {
|
||||||
if (curr->size >= size + (sizeof(free_chunk_t) + 8)) {
|
if (curr->size >= size + (sizeof(free_chunk_t) + 8)) {
|
||||||
@@ -85,7 +83,7 @@ void *memory_allocate(uint64_t size) {
|
|||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = curr->next;
|
prev->next = curr->next;
|
||||||
} else {
|
} else {
|
||||||
free_list = curr->next;
|
proc->heap = curr->next;
|
||||||
}
|
}
|
||||||
void *result = (void *)((uint8_t *)curr + sizeof(free_chunk_t));
|
void *result = (void *)((uint8_t *)curr + sizeof(free_chunk_t));
|
||||||
memory_set(0, size - sizeof(free_chunk_t), result);
|
memory_set(0, size - sizeof(free_chunk_t), result);
|
||||||
@@ -99,9 +97,9 @@ void *memory_allocate(uint64_t size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_free(void *pointer) {
|
void memory_free(process_t *proc, void *pointer) {
|
||||||
free_chunk_t *chunk = (free_chunk_t *)((uint8_t *)pointer - sizeof(free_chunk_t));
|
free_chunk_t *chunk = (free_chunk_t *)((uint8_t *)pointer - sizeof(free_chunk_t));
|
||||||
chunk->next = free_list;
|
chunk->next = proc->heap;
|
||||||
free_list = chunk;
|
proc->heap = chunk;
|
||||||
// TODO Merge adjacent free chunks.
|
// TODO Merge adjacent free chunks.
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -3,11 +3,18 @@
|
|||||||
#include "src/panic.h"
|
#include "src/panic.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void memory_init();
|
typedef struct process process_t;
|
||||||
|
|
||||||
void *memory_allocate(uint64_t size);
|
typedef struct free_chunk {
|
||||||
|
uint64_t size; // header + data
|
||||||
|
struct free_chunk *next;
|
||||||
|
} free_chunk_t;
|
||||||
|
|
||||||
void memory_free(void *pointer);
|
void memory_init(process_t *kernel);
|
||||||
|
|
||||||
|
void *memory_allocate(process_t *proc, uint64_t size);
|
||||||
|
|
||||||
|
void memory_free(process_t *proc, void *pointer);
|
||||||
|
|
||||||
static inline void memory_set(uint8_t value, uint64_t bytes, void *to) {
|
static inline void memory_set(uint8_t value, uint64_t bytes, void *to) {
|
||||||
__asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory");
|
__asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory");
|
||||||
|
|||||||
+11
-12
@@ -1,18 +1,17 @@
|
|||||||
#include "src/path.h"
|
#include "src/path.h"
|
||||||
#include "src/fs.h"
|
|
||||||
#include "src/memory.h"
|
#include "src/memory.h"
|
||||||
|
#include "src/process.h"
|
||||||
#include "src/string.h"
|
#include "src/string.h"
|
||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
path_t *path_open(const fs_node_t *root, const path_t *source, char *path) {
|
path_t *path_open(process_t *proc, const path_t *source, char *path) {
|
||||||
path_t *result = memory_allocate(sizeof(path_t));
|
path_t *result = memory_allocate(proc, sizeof(path_t));
|
||||||
|
|
||||||
char *path_components[PATH_DEPTH];
|
char *path_components[PATH_DEPTH];
|
||||||
uint8_t path_length = (uint8_t)string_split(path, '/', PATH_DEPTH, path_components);
|
uint8_t path_length = (uint8_t)string_split(path, '/', PATH_DEPTH, path_components);
|
||||||
if (!string_empty(path_components[0])) {
|
if (!string_empty(path_components[0])) {
|
||||||
for (uint8_t i = 0; i < source->depth; i++) {
|
for (uint8_t i = 0; i < source->depth; i++) {
|
||||||
result->stack[result->depth++] = fs_open_again(source->stack[i]);
|
result->stack[result->depth++] = fs_open_again(proc, source->stack[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,13 +20,13 @@ path_t *path_open(const fs_node_t *root, const path_t *source, char *path) {
|
|||||||
continue;
|
continue;
|
||||||
} else if (string_equal(path_components[i], "..")) {
|
} else if (string_equal(path_components[i], "..")) {
|
||||||
if (result->depth) {
|
if (result->depth) {
|
||||||
fs_close(result->stack[--result->depth]);
|
fs_close(proc, result->stack[--result->depth]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root;
|
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : proc->root;
|
||||||
fs_node_t *next = prev->is_dir ? fs_open_by(prev, path_components[i]) : NUL;
|
fs_node_t *next = prev->is_dir ? fs_open_by(proc, prev, path_components[i]) : NUL;
|
||||||
if (!next || result->depth >= PATH_DEPTH) {
|
if (!next || result->depth >= PATH_DEPTH) {
|
||||||
path_close(result);
|
path_close(proc, result);
|
||||||
return NUL;
|
return NUL;
|
||||||
} else {
|
} else {
|
||||||
result->stack[result->depth++] = next;
|
result->stack[result->depth++] = next;
|
||||||
@@ -38,9 +37,9 @@ path_t *path_open(const fs_node_t *root, const path_t *source, char *path) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_close(path_t *path) {
|
void path_close(process_t *proc, path_t *path) {
|
||||||
for (uint64_t i = 0; i < path->depth; i++) {
|
for (uint64_t i = 0; i < path->depth; i++) {
|
||||||
fs_close(path->stack[i]);
|
fs_close(proc, path->stack[i]);
|
||||||
}
|
}
|
||||||
memory_free(path);
|
memory_free(proc, path);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/fs.h"
|
#include "src/fs.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define PATH_DEPTH 255
|
#define PATH_DEPTH 255
|
||||||
|
|
||||||
|
typedef struct process process_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
fs_node_t *stack[PATH_DEPTH];
|
fs_node_t *stack[PATH_DEPTH];
|
||||||
uint8_t depth;
|
uint8_t depth;
|
||||||
} path_t;
|
} path_t;
|
||||||
|
|
||||||
path_t *path_open(const fs_node_t *root, const path_t *source, char *path);
|
path_t *path_open(process_t *proc, const path_t *source, char *path);
|
||||||
|
|
||||||
void path_close(path_t *path);
|
void path_close(process_t *proc, path_t *path);
|
||||||
|
|||||||
+8
-3
@@ -1,13 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/fs.h"
|
|
||||||
#include "src/path.h"
|
#include "src/path.h"
|
||||||
#include "src/stream.h"
|
#include "src/stream.h"
|
||||||
#include "src/string.h"
|
#include "src/string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct free_chunk free_chunk_t;
|
||||||
path_t *cwd;
|
|
||||||
|
typedef struct process {
|
||||||
|
struct process *kernel;
|
||||||
|
uint64_t *pml4;
|
||||||
|
free_chunk_t *heap;
|
||||||
fs_node_t *root;
|
fs_node_t *root;
|
||||||
|
path_t *cwd;
|
||||||
stream_t *stdin;
|
stream_t *stdin;
|
||||||
stream_t *stdout;
|
stream_t *stdout;
|
||||||
} process_t;
|
} process_t;
|
||||||
|
|||||||
+18
-21
@@ -1,7 +1,5 @@
|
|||||||
#include "src/string.h"
|
#include "src/string.h"
|
||||||
#include "src/memory.h"
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) {
|
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) {
|
||||||
while (count--) {
|
while (count--) {
|
||||||
@@ -164,41 +162,39 @@ uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *string_format(const char *format, ...) {
|
uint64_t string_format(const char *format, uint64_t max, char *output, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, output);
|
||||||
|
|
||||||
uint64_t limit = 1023;
|
uint64_t limit = max - 1;
|
||||||
|
|
||||||
char *result = memory_allocate(limit + 1);
|
|
||||||
|
|
||||||
uint64_t fi = 0, ri = 0;
|
uint64_t fi = 0, ri = 0;
|
||||||
while (format[fi] && ri < limit) {
|
while (format[fi] && ri < limit) {
|
||||||
if (format[fi] != '%') {
|
if (format[fi] != '%') {
|
||||||
result[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
} else {
|
} else {
|
||||||
switch (format[fi + 1]) {
|
switch (format[fi + 1]) {
|
||||||
case 'c':
|
case 'c':
|
||||||
result[ri++] = (char)va_arg(args, int);
|
output[ri++] = (char)va_arg(args, int);
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
string_int_to_decimal(va_arg(args, int64_t), limit - ri, result + ri);
|
string_int_to_decimal(va_arg(args, int64_t), limit - ri, output + ri);
|
||||||
while (result[ri]) {
|
while (output[ri]) {
|
||||||
ri++;
|
ri++;
|
||||||
}
|
}
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, result + ri);
|
string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
while (result[ri]) {
|
while (output[ri]) {
|
||||||
ri++;
|
ri++;
|
||||||
}
|
}
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
string_uint_to_hex(va_arg(args, uint64_t), limit - ri, result + ri);
|
string_uint_to_hex(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
while (result[ri]) {
|
while (output[ri]) {
|
||||||
ri++;
|
ri++;
|
||||||
}
|
}
|
||||||
fi += 2;
|
fi += 2;
|
||||||
@@ -206,25 +202,26 @@ char *string_format(const char *format, ...) {
|
|||||||
case 's': {
|
case 's': {
|
||||||
char *s = va_arg(args, char *);
|
char *s = va_arg(args, char *);
|
||||||
while (*s && ri < limit) {
|
while (*s && ri < limit) {
|
||||||
result[ri++] = *s;
|
output[ri++] = *s;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '%': {
|
case '%': {
|
||||||
result[ri++] = '%';
|
output[ri++] = '%';
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
result[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
result[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[ri] = '\0';
|
output[ri] = '\0';
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
|
||||||
|
return ri;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,4 +20,4 @@ uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result);
|
|||||||
|
|
||||||
uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result);
|
uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
char *string_format(const char *format, ...);
|
uint64_t string_format(const char *format, uint64_t max, char *output, ...);
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#include "src/vga.h"
|
#include "src/vga.h"
|
||||||
#include "src/memory.h"
|
#include "src/memory.h"
|
||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
static uint16_t *vga = (uint16_t *)0x000B8000;
|
static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000;
|
||||||
static uint16_t color = (uint16_t)0x0F << 8;
|
static uint16_t color = (uint16_t)0x0F << 8;
|
||||||
static uint16_t offset = 0;
|
static uint16_t offset = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user