Fixed paging fully now. Kernel is loaded with virtual memory enabled. Just need to write an allocator and make kernel use virtual memory addresses for its stuff. Restructured codebase to be less messy. Updated Makefile to put binary files under build/ rather than in root directory
This commit is contained in:
parent
6328062d4f
commit
1225529708
52
Makefile
52
Makefile
@ -1,45 +1,49 @@
|
||||
CFLAGS = -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast
|
||||
LDFLAGS =
|
||||
|
||||
DISK_IMG_FILES = kernel.bin
|
||||
KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o paging.o
|
||||
DISK_IMG_FILES = build/kernel/kernel.bin
|
||||
KERNEL_OBJS = build/c_code_entry.o build/kernel/screenstuff.o build/kernel/io.o build/kernel/idt.o build/kernel/keyboard.o build/kernel/strings.o build/kernel/atapio.o build/kernel/kernel.o build/kernel/paging.o
|
||||
STAGE2_OBS = build/c_code_entry.o build/boot_stage2/io.o build/boot_stage2/atapio.o build/boot_stage2/strings.o build/boot_stage2/screenstuff.o build/boot_stage2/stage2.o build/boot_stage2/paging.o
|
||||
|
||||
run: disk.img
|
||||
qemu-system-x86_64 disk.img
|
||||
|
||||
disk.img: clean boot.sector boot.stage2 $(DISK_IMG_FILES)
|
||||
disk.img: clean prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES)
|
||||
dd if=/dev/zero of=disk.img count=43 bs=100k
|
||||
dd if=boot.sector of=disk.img conv=notrunc
|
||||
dd obs=512 seek=1 if=boot.stage2 of=disk.img conv=notrunc
|
||||
dd if=build/boot/boot.bin of=disk.img conv=notrunc
|
||||
dd obs=512 seek=1 if=build/boot_stage2/boot.bin of=disk.img conv=notrunc
|
||||
mount disk.img img.d
|
||||
cp *.bin img.d/
|
||||
cp $(DISK_IMG_FILES) img.d/
|
||||
cp hello.txt img.d/
|
||||
umount img.d
|
||||
chmod 777 disk.img
|
||||
|
||||
prepare:
|
||||
mkdir -p img.d
|
||||
mkdir -p build/boot
|
||||
mkdir -p build/boot_stage2
|
||||
mkdir -p build/kernel
|
||||
|
||||
clean:
|
||||
rm $(DISK_IMG_FILES) $(KERNEL32_OBJS) boot.sector disk.img || true
|
||||
rm -rf build
|
||||
|
||||
boot.sector: boot.asm
|
||||
build/boot/boot.bin: src/boot/boot.asm
|
||||
nasm $< -o $@
|
||||
|
||||
boot.stage2: boot_stage2.ld boot.stage2.o
|
||||
ld $(LDFLAGS) -T $< boot.stage2.o
|
||||
build/boot_stage2/boot.bin: src/boot_stage2/boot_stage2.ld $(STAGE2_OBS)
|
||||
ld $(LDFLAGS) -T $< $(STAGE2_OBS)
|
||||
|
||||
boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o
|
||||
build/kernel/kernel.bin: src/kernel/kernel.ld $(KERNEL_OBJS)
|
||||
ld $(LDFLAGS) -T $< $(KERNEL_OBJS)
|
||||
|
||||
build/boot_stage2/stage2.o: src/boot_stage2/main.c
|
||||
gcc $(CFLAGS) -o $@ -c $<
|
||||
|
||||
%.bin: %.asm
|
||||
nasm $< -o $@
|
||||
|
||||
kernel.bin: kernel.ld $(KERNEL32_OBJS)
|
||||
ld $(LDFLAGS) -T $< $(KERNEL32_OBJS)
|
||||
|
||||
%.o: src/kernel/%.asm
|
||||
nasm -felf32 $< -o $@
|
||||
|
||||
%.o: src/%.asm
|
||||
nasm -felf32 $< -o $@
|
||||
|
||||
%.o: src/kernel/%.c
|
||||
build/kernel/%.o: src/kernel/%.c
|
||||
gcc $(CFLAGS) -o $@ -c $<
|
||||
|
||||
build/boot_stage2/%.o: src/boot_stage2/%.c
|
||||
gcc $(CFLAGS) -o $@ -c $<
|
||||
|
||||
build/%.o: src/%.asm
|
||||
nasm -felf32 $< -o $@
|
@ -1,15 +0,0 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
|
||||
INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o)
|
||||
OUTPUT(boot.stage2)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x7E00;
|
||||
|
||||
.text : {
|
||||
c_code_entry.o(.text)
|
||||
boot.stage2.o(.text)
|
||||
*(.text)
|
||||
}
|
||||
}
|
15
kernel.ld
15
kernel.ld
@ -1,15 +0,0 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
|
||||
OUTPUT(kernel.bin)
|
||||
|
||||
SECTIONS {
|
||||
. = 0xc0000000;
|
||||
|
||||
.text : {
|
||||
c_code_entry.o(.text)
|
||||
kernel.o(.text)
|
||||
*(.text)
|
||||
heap_section = .;
|
||||
}
|
||||
}
|
122
src/boot_stage2/atapio.c
Normal file
122
src/boot_stage2/atapio.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include "atapio.h"
|
||||
|
||||
// Disk code
|
||||
|
||||
// Primary ATA Bus: 0x1f0 to 0x1f7
|
||||
// Device Control Register: 0x3f6
|
||||
// Secondary ATA Bus: 0x170 to 0x177
|
||||
// Device Control Register: 0x376
|
||||
|
||||
|
||||
uint16_t identify_result[256];
|
||||
uint32_t total_28_lbas = 0;
|
||||
|
||||
uint8_t* rootDirEntries = 0x1000000;
|
||||
uint16_t* FAT1 = 0x1002000;
|
||||
|
||||
uint16_t countReserved;
|
||||
uint8_t countFATs;
|
||||
uint16_t countRDEs;
|
||||
uint16_t sectorsPerFAT;
|
||||
|
||||
|
||||
void init_atapio() {
|
||||
countReserved = *(uint16_t*)0x7c0e;
|
||||
countFATs = *(uint8_t*)0x7c10;
|
||||
countRDEs = *(uint16_t*)0x7c11;
|
||||
sectorsPerFAT = *(uint16_t*)0x7c16;
|
||||
|
||||
// Select Drive 0 on the Primary Bus
|
||||
outb(0x1f6, 0xa0);
|
||||
|
||||
// Set sector count to 0 for IDENTIFY
|
||||
outb(0x1f2, 0);
|
||||
// Set LBAlo to 0
|
||||
outb(0x1f3, 0);
|
||||
// Set LBAmid to 0
|
||||
outb(0x1f4, 0);
|
||||
// Set LBAhi to 0
|
||||
outb(0x1f5, 0);
|
||||
|
||||
// Send IDENTIFY command
|
||||
outb(0x1f7, 0xec);
|
||||
|
||||
uint8_t status = inb(0x1f7);
|
||||
if (status) {
|
||||
while ((status = inb(0x1f7)) & 0x80);
|
||||
|
||||
if ( !(inb(0x1f4) || inb(0x1f5)) ) {
|
||||
while ( !(status & 8 || status & 1) )
|
||||
status = inb(0x1f7);
|
||||
|
||||
if (!(status & 1)) {
|
||||
for (int index=0; index<256; index++)
|
||||
identify_result[index] = inw(0x1f0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total_28_lbas = *(uint32_t*)(identify_result+60);
|
||||
|
||||
// We've initialised now, let's load the FAT and RootDirEntries.
|
||||
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, rootDirEntries);
|
||||
read_sectors(countReserved, sectorsPerFAT, FAT1);
|
||||
}
|
||||
|
||||
void read_sector(uint32_t address, uint8_t* buffer) {
|
||||
outb(0x1f6, 0xe0 | ((address>>24)&0x0f));
|
||||
// Read a single sector
|
||||
outb(0x1f2, 1);
|
||||
// Set LBAlo, LBAmid and LBAhi
|
||||
outb(0x1f3, address);
|
||||
outb(0x1f4, address>>8);
|
||||
outb(0x1f5, address>>16);
|
||||
|
||||
// Send read command
|
||||
outb(0x1f7, 0x20);
|
||||
// Poll
|
||||
uint8_t status = inb(0x1f7);
|
||||
while ( (status & 0x80) && !(status & 8) )
|
||||
status = inb(0x1f7);
|
||||
|
||||
for (int index=0; index<256; index++)
|
||||
((uint16_t*)buffer)[index] = inw(0x1f0);
|
||||
}
|
||||
|
||||
void read_sectors(uint32_t address, int count, uint8_t* buffer) {
|
||||
for (int i=0; i<count; i++) {
|
||||
read_sector(address+i, buffer+512*i);
|
||||
for (int i=0; i<15; i++)
|
||||
inb(0x1f7);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t file_exists(char* filename) {
|
||||
for (int i=0; i<countRDEs; i++) {
|
||||
bool found = strcmp(rootDirEntries+(i*32), filename, 11);
|
||||
if (found) {
|
||||
uint16_t* correctEntry = (rootDirEntries+(i*32));
|
||||
return correctEntry[13];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void load_file(char* filename, uint8_t* destination) {
|
||||
uint16_t location = file_exists(filename);
|
||||
if (!location)
|
||||
return;
|
||||
|
||||
int offset = 0;
|
||||
|
||||
bool loaded = false;
|
||||
while (!loaded) {
|
||||
uint16_t fromSector = location + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
|
||||
read_sector(fromSector, destination+offset);
|
||||
offset += 512;
|
||||
|
||||
location = FAT1[location++];
|
||||
if (location == 0xffff)
|
||||
loaded = true;
|
||||
}
|
||||
}
|
16
src/boot_stage2/atapio.h
Normal file
16
src/boot_stage2/atapio.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef ATA_PIO
|
||||
#define ATA_PIO
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "types.h"
|
||||
#include "strings.h"
|
||||
|
||||
void init_atapio();
|
||||
void read_sector(uint32_t address, uint8_t* buffer);
|
||||
void read_sectors(uint32_t address, int count, uint8_t* buffer);
|
||||
uint16_t file_exists(char* filename);
|
||||
void load_file(char* filename, uint8_t* location);
|
||||
|
||||
#endif
|
14
src/boot_stage2/boot_stage2.ld
Normal file
14
src/boot_stage2/boot_stage2.ld
Normal file
@ -0,0 +1,14 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
|
||||
OUTPUT(build/boot_stage2/boot.bin)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x7E00;
|
||||
|
||||
.text : {
|
||||
build/c_code_entry.o(.text)
|
||||
build/boot_stage2/stage2.o(.text)
|
||||
build/boot_stage2/*(.text)
|
||||
}
|
||||
}
|
19
src/boot_stage2/io.c
Normal file
19
src/boot_stage2/io.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include "io.h"
|
||||
|
||||
void outb(uint16_t portnumber, uint8_t data) {
|
||||
asm volatile("outb %0, %1" : : "a" (data), "Nd" (portnumber));
|
||||
}
|
||||
uint8_t inb(uint16_t portnumber) {
|
||||
uint8_t result;
|
||||
asm volatile("inb %1, %0" : "=a" (result) : "Nd" (portnumber));
|
||||
return result;
|
||||
}
|
||||
|
||||
void outw(uint16_t portnumber, uint16_t data) {
|
||||
asm volatile("outw %0, %1" : : "a" (data), "Nd" (portnumber));
|
||||
}
|
||||
uint16_t inw(uint16_t portnumber) {
|
||||
uint16_t result;
|
||||
asm volatile("inw %1, %0" : "=a" (result) : "Nd" (portnumber));
|
||||
return result;
|
||||
}
|
12
src/boot_stage2/io.h
Normal file
12
src/boot_stage2/io.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void outb(uint16_t portnumber, uint8_t data);
|
||||
uint8_t inb(uint16_t portnumber);
|
||||
|
||||
void outw(uint16_t portnumber, uint16_t data);
|
||||
uint16_t inw(uint16_t portnumber);
|
||||
|
||||
#endif
|
@ -1,6 +1,6 @@
|
||||
#include "../kernel/atapio.h"
|
||||
#include "../kernel/screenstuff.h"
|
||||
#include "../kernel/paging.h"
|
||||
#include "atapio.h"
|
||||
#include "screenstuff.h"
|
||||
#include "paging.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t base_low;
|
||||
@ -120,7 +120,8 @@ void main() {
|
||||
map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000
|
||||
map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000
|
||||
|
||||
map_4k_phys_to_virt(0x8000, 0x8000, kernel_page_directory, kernel_page_tables);
|
||||
map_many_4k_phys_to_virt(0x7000, 0x7000, kernel_page_directory, kernel_page_tables, 2);
|
||||
map_4k_phys_to_virt(0x8f000, 0x8f000, kernel_page_directory, kernel_page_tables);
|
||||
|
||||
load_file("KERNEL BIN", kernel_location);
|
||||
|
||||
|
46
src/boot_stage2/paging.c
Normal file
46
src/boot_stage2/paging.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "paging.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t page_offset : 12;
|
||||
uint32_t pt_index : 10;
|
||||
uint32_t pd_index : 10;
|
||||
}__attribute__((packed)) split_addr;
|
||||
|
||||
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) {
|
||||
split_addr* split = (split_addr*)&virtual;
|
||||
|
||||
page_directory[split->pd_index] = (PDE){
|
||||
.address = (uint32_t)(page_tables[split->pd_index]) >> 12,
|
||||
.available = 0,
|
||||
.page_4mb = 0,
|
||||
.accessed = 0,
|
||||
.disable_cache = 0,
|
||||
.write_through_cache = 0,
|
||||
.privilege = 0,
|
||||
.present = 1,
|
||||
.read_write = 1,
|
||||
|
||||
.ignored = 0,
|
||||
.ignored2 = 0
|
||||
};
|
||||
|
||||
page_tables[split->pd_index][split->pt_index] = (PTE){
|
||||
.address = physical >> 12,
|
||||
.available = 0,
|
||||
.global = 0,
|
||||
.accessed = 0,
|
||||
.disable_cache = 0,
|
||||
.dirty = 0,
|
||||
.write_through_cache = 0,
|
||||
.privilege = 0,
|
||||
.present = 1,
|
||||
.read_write = 1,
|
||||
|
||||
.ignored = 0
|
||||
};
|
||||
}
|
||||
|
||||
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) {
|
||||
for (int i=0; i<count; i++)
|
||||
map_4k_phys_to_virt(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);
|
||||
}
|
37
src/boot_stage2/paging.h
Normal file
37
src/boot_stage2/paging.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef PAGING_H
|
||||
#define PAGING_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t present : 1;
|
||||
uint32_t read_write : 1;
|
||||
uint32_t privilege : 1;
|
||||
uint32_t write_through_cache : 1;
|
||||
uint32_t disable_cache : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t ignored2 : 1;
|
||||
uint32_t page_4mb : 1;
|
||||
uint32_t ignored : 1;
|
||||
uint32_t available : 3;
|
||||
uint32_t address : 20;
|
||||
}__attribute__((packed)) PDE;
|
||||
|
||||
typedef struct {
|
||||
uint32_t present : 1;
|
||||
uint32_t read_write : 1;
|
||||
uint32_t privilege : 1;
|
||||
uint32_t write_through_cache : 1;
|
||||
uint32_t disable_cache : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t dirty : 1;
|
||||
uint32_t ignored : 1;
|
||||
uint32_t global : 1;
|
||||
uint32_t available : 3;
|
||||
uint32_t address : 20;
|
||||
}__attribute__((packed)) PTE;
|
||||
|
||||
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables);
|
||||
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
|
||||
#endif
|
161
src/boot_stage2/screenstuff.c
Normal file
161
src/boot_stage2/screenstuff.c
Normal file
@ -0,0 +1,161 @@
|
||||
#include "screenstuff.h"
|
||||
|
||||
uint16_t* VMEM_ADDR = (uint16_t*)0xb8000;
|
||||
const int TERM_WIDTH = 80;
|
||||
const int TERM_HEIGHT = 25;
|
||||
|
||||
int cursor_x = 0;
|
||||
int cursor_y = 0;
|
||||
|
||||
uint16_t get_curpos() {
|
||||
uint16_t cursor_position = 0;
|
||||
uint8_t* cursor_position_split = (uint8_t*)&cursor_position;
|
||||
outb(0x3D4, 0x0F);
|
||||
cursor_position_split[0] = inb(0x3D5);
|
||||
outb(0x3D4, 0x0E);
|
||||
cursor_position_split[1] = inb(0x3D5);
|
||||
return cursor_position;
|
||||
}
|
||||
|
||||
void init_term() {
|
||||
uint16_t cursor_position = get_curpos();
|
||||
|
||||
cursor_y = cursor_position / TERM_WIDTH;
|
||||
cursor_x = cursor_position % TERM_WIDTH;
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
for (int i=0; i<TERM_WIDTH*TERM_HEIGHT; i++) {
|
||||
VMEM_ADDR[i] = 0x0720;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_line(int line) {
|
||||
for (int x=0; x<TERM_WIDTH; x++) {
|
||||
VMEM_ADDR[TERM_WIDTH*line + x] = 0x0720;
|
||||
}
|
||||
}
|
||||
|
||||
void set_curpos_raw(int curpos) {
|
||||
uint8_t* cursor_position_split = (uint8_t*)&curpos;
|
||||
outb(0x3D4, 0x0F);
|
||||
outb(0x3D5, cursor_position_split[0]);
|
||||
outb(0x3D4, 0x0E);
|
||||
outb(0x3D5, cursor_position_split[1]);
|
||||
|
||||
cursor_x = (*(uint16_t*)cursor_position_split) % TERM_WIDTH;
|
||||
cursor_y = (*(uint16_t*)cursor_position_split) / TERM_WIDTH;
|
||||
}
|
||||
|
||||
void set_curpos(int x, int y) {
|
||||
set_curpos_raw(y * TERM_WIDTH + x);
|
||||
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
int int_to_decimal(unsigned int number, char* string_buffer) {
|
||||
for (int i=0; i<11; i++)
|
||||
string_buffer[i] = 0;
|
||||
|
||||
int index = 9;
|
||||
unsigned int acc = number;
|
||||
if (acc == 0)
|
||||
string_buffer[index--] = '0';
|
||||
while (acc != 0) {
|
||||
string_buffer[index--] = 0x30+(acc%10);
|
||||
acc /= 10;
|
||||
}
|
||||
return (index+1);
|
||||
}
|
||||
|
||||
char dec_to_hex[16] = "0123456789abcdef";
|
||||
int int_to_hex(unsigned int number, char* string_buffer) {
|
||||
for (int i=0; i<8; i++)
|
||||
string_buffer[i] = '0';
|
||||
string_buffer[8] = 0;
|
||||
|
||||
int index = 7;
|
||||
unsigned int acc = number;
|
||||
if (acc == 0)
|
||||
string_buffer[index--] = '0';
|
||||
while (acc != 0) {
|
||||
string_buffer[index--] = dec_to_hex[acc%0x10];
|
||||
acc /= 0x10;
|
||||
}
|
||||
return (index+1);
|
||||
}
|
||||
|
||||
void printf(const char* string, ...) {
|
||||
va_list ptr;
|
||||
va_start(ptr, string);
|
||||
|
||||
int index = 0;
|
||||
int count = 0;
|
||||
char current;
|
||||
while (current=string[index++]) {
|
||||
count++;
|
||||
if (current == '\n') {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
|
||||
if (cursor_x == TERM_WIDTH) {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
|
||||
if (cursor_y == TERM_HEIGHT) {
|
||||
for (int i=1; i<TERM_HEIGHT; i++) {
|
||||
for (int x=0; x<TERM_WIDTH; x++) {
|
||||
int from = i * TERM_WIDTH + x;
|
||||
int to = (i-1) * TERM_WIDTH + x;
|
||||
VMEM_ADDR[to] = VMEM_ADDR[from];
|
||||
}
|
||||
}
|
||||
clear_line(24);
|
||||
cursor_y--;
|
||||
}
|
||||
|
||||
if (current == '%') {
|
||||
int type = string[index++];
|
||||
int offset;
|
||||
switch (type) {
|
||||
case 'd':
|
||||
char decimal_buffer[11];
|
||||
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
|
||||
printf(decimal_buffer + offset);
|
||||
break;
|
||||
case 'x':
|
||||
char hex_buffer[8];
|
||||
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
|
||||
printf(hex_buffer);
|
||||
break;
|
||||
case 's':
|
||||
printf(va_arg(ptr, const char*));
|
||||
break;
|
||||
case 'c':
|
||||
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
|
||||
int promoted = va_arg(ptr, int);
|
||||
char charred = promoted;
|
||||
VMEM_ADDR[mem_pos] = charred + (0x07<<8);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current != '\n') {
|
||||
int mem_pos = cursor_y * TERM_WIDTH + cursor_x++;
|
||||
VMEM_ADDR[mem_pos] = current + (0x07<<8);
|
||||
}
|
||||
}
|
||||
|
||||
set_curpos(cursor_x, cursor_y);
|
||||
|
||||
va_end(ptr);
|
||||
}
|
||||
|
||||
void non_moving_put(char chr) {
|
||||
int mem_pos = cursor_y * TERM_WIDTH + cursor_x;
|
||||
VMEM_ADDR[mem_pos] = chr + (0x07<<8);
|
||||
}
|
19
src/boot_stage2/screenstuff.h
Normal file
19
src/boot_stage2/screenstuff.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef SCREENSTUFF_H
|
||||
#define SCREENSTUFF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "types.h"
|
||||
#include "io.h"
|
||||
|
||||
uint16_t get_curpos();
|
||||
void init_term();
|
||||
void clear_screen();
|
||||
void clear_line(int line);
|
||||
void set_curpos_raw(int curpos);
|
||||
void set_curpos(int x, int y);
|
||||
int int_to_decimal(unsigned int number, char* string_buffer);
|
||||
int int_to_hex(unsigned int number, char* string_buffer);
|
||||
void printf(const char* string, ...);
|
||||
void non_moving_put(char chr);
|
||||
|
||||
#endif
|
69
src/boot_stage2/strings.c
Normal file
69
src/boot_stage2/strings.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include "strings.h"
|
||||
|
||||
bool strcmp(char* a, char* b, int max) {
|
||||
int index = 0;
|
||||
while (index < max) {
|
||||
if (a[index] != b[index])
|
||||
return false;
|
||||
index++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char* split_on_first(char delimeter, char* string) {
|
||||
int index = 0;
|
||||
char current;
|
||||
|
||||
while (current = string[index++]) {
|
||||
if (current == delimeter) {
|
||||
string[index-1] = 0;
|
||||
return string+index;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int string_split(char delimeter, char* string, char** pointer_array) {
|
||||
int index = 0;
|
||||
int last_split_index = 0;
|
||||
int split_count = 0;
|
||||
|
||||
char current;
|
||||
|
||||
while (current = string[index]) {
|
||||
if (current == delimeter) {
|
||||
string[index] = 0;
|
||||
pointer_array[split_count++] = (string+last_split_index);
|
||||
last_split_index = (index+1);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// Add remaining part of the string to the pointer_array
|
||||
pointer_array[split_count] = (string+last_split_index);
|
||||
|
||||
return split_count;
|
||||
}
|
||||
|
||||
void decode_filename(char* nice_name, char* filenamebuffer) {
|
||||
// Clear filenamebuffer
|
||||
for (int i=0; i<11; i++)
|
||||
filenamebuffer[i] = ' ';
|
||||
filenamebuffer[11] = 0;
|
||||
|
||||
int fbIndex = 0;
|
||||
for (int i=0; i<12; i++) {
|
||||
if (nice_name[i] == 0)
|
||||
return;
|
||||
if (nice_name[i] == '.') {
|
||||
fbIndex = 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nice_name[i] >= 0x61 && nice_name[i] <= 0x7f)
|
||||
filenamebuffer[fbIndex++] = nice_name[i] - 32;
|
||||
else
|
||||
filenamebuffer[fbIndex++] = nice_name[i];
|
||||
}
|
||||
}
|
11
src/boot_stage2/strings.h
Normal file
11
src/boot_stage2/strings.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef STRINGS_H
|
||||
#define STRINGS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool strcmp(char* a, char* b, int max);
|
||||
char* split_on_first(char delimeter, char* string);
|
||||
int string_split(char delimeter, char* string, char** pointer_array);
|
||||
void decode_filename(char* nice_name, char* filenamebuffer);
|
||||
|
||||
#endif
|
11
src/boot_stage2/types.h
Normal file
11
src/boot_stage2/types.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
typedef char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef long int int32_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
|
||||
#endif
|
15
src/kernel/kernel.ld
Normal file
15
src/kernel/kernel.ld
Normal file
@ -0,0 +1,15 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
|
||||
OUTPUT(build/kernel/kernel.bin)
|
||||
|
||||
SECTIONS {
|
||||
. = 0xc0000000;
|
||||
|
||||
.text : {
|
||||
build/c_code_entry.o(.text)
|
||||
build/kernel/kernel.o(.text)
|
||||
build/kernel/*(.text)
|
||||
heap_section = .;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user