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:
@@ -0,0 +1,141 @@
|
||||
[ORG 0x7C00]
|
||||
[BITS 16]
|
||||
|
||||
jmp short bootcode
|
||||
nop
|
||||
|
||||
bpOEMid db "XNOE "
|
||||
|
||||
bpBytesPerSector dw 512
|
||||
bpSectorsPerCluster db 1
|
||||
bpReservedSectors dw 32 ; We should reserve some sectors. Boot sector + stage2
|
||||
bpNoFATs db 2
|
||||
bpRootDirEntries dw 256
|
||||
bpLVSectors dw 8586
|
||||
bpMediumID db 0xF8
|
||||
bpSectorsPerFat dw 34
|
||||
bpSectorsPerTrack dw 18
|
||||
bpHeads dw 2
|
||||
bpHiddenSectors dw 0
|
||||
|
||||
TIMES 36 - ($ - $$) db 0
|
||||
|
||||
bpDriveNo db 0
|
||||
db 0
|
||||
bpSignature db 0x29
|
||||
bpVolumeID dd 0x0
|
||||
bpVolumeLabel db "XNOE OS "
|
||||
bpFileSystem db "FAT16 "
|
||||
|
||||
bootcode:
|
||||
|
||||
mov byte [bpDriveNo], dl
|
||||
|
||||
; Get the disk configuration from the BIOS
|
||||
mov ah, 08h
|
||||
int 13h
|
||||
|
||||
add dh, 1
|
||||
movzx dx, dh
|
||||
mov word [bpHeads], dx
|
||||
and cl, 03fh
|
||||
movzx cx, cl
|
||||
mov word [bpSectorsPerTrack], cx
|
||||
|
||||
; Load the stage2 (32-bit) from the next sectors
|
||||
; Load it at 0x7e00
|
||||
mov ax, 7e0h
|
||||
mov es, ax
|
||||
xor bx, bx
|
||||
|
||||
mov ax, 2 ; Begin with the 2nd sector
|
||||
call prep_i13
|
||||
mov al, 31 ; Load the next 9 sectors (4.5k)
|
||||
int 13h
|
||||
|
||||
; We need to get the memory configuration from the BIOS now
|
||||
; To do this we can use int 15h eax=e820h
|
||||
; We will load the e820 data to 0x20000
|
||||
|
||||
mov ax, 2000h
|
||||
mov es, ax
|
||||
xor di, di
|
||||
xor ebx, ebx
|
||||
|
||||
get_memory_map_loop:
|
||||
mov edx, 0x534D4150
|
||||
mov ecx, 24
|
||||
|
||||
mov eax, 0xe820
|
||||
int 15h
|
||||
jc mmap_finish
|
||||
|
||||
cmp ebx, 0
|
||||
je mmap_finish
|
||||
|
||||
add di, 24
|
||||
jmp get_memory_map_loop
|
||||
|
||||
mmap_finish:
|
||||
; Now we should prepare to enter in to protected mode for the sole purpose of running the stage2 bootloader
|
||||
|
||||
; Enable the A20 line
|
||||
in al, 0x92
|
||||
or al, 2
|
||||
out 0x92, al
|
||||
|
||||
; Load the temporary GDT
|
||||
cli
|
||||
lgdt [gdt_desc]
|
||||
mov eax, cr0
|
||||
or eax, 1
|
||||
mov cr0, eax
|
||||
|
||||
jmp 08h:7e00h ; Far jump to where we loaded the stage 2
|
||||
|
||||
; In ax with sector addr, out correct values for int 13h
|
||||
prep_i13:
|
||||
xor dx, dx
|
||||
div word [bpSectorsPerTrack]
|
||||
|
||||
push dx
|
||||
|
||||
xor dx, dx
|
||||
div word [bpHeads]
|
||||
|
||||
mov ch, al
|
||||
mov dh, dl
|
||||
mov dl, byte [bpDriveNo]
|
||||
|
||||
pop ax
|
||||
mov cl, al
|
||||
|
||||
mov al, 1
|
||||
mov ah, 2
|
||||
|
||||
ret
|
||||
|
||||
gdt:
|
||||
null:
|
||||
dq 0
|
||||
code:
|
||||
dw 0xffff
|
||||
dw 0
|
||||
db 0
|
||||
db 10011010b
|
||||
db 11001111b
|
||||
db 0
|
||||
data:
|
||||
dw 0xffff
|
||||
dw 0
|
||||
db 0
|
||||
db 10010010b
|
||||
db 11001111b
|
||||
db 0
|
||||
gdt_end:
|
||||
gdt_desc:
|
||||
dw gdt_desc - gdt_end - 1
|
||||
dd gdt
|
||||
|
||||
TIMES 510 - ($ - $$) db 0
|
||||
DW 0xAA55
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 = .;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user