mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Began rewrite
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
include ../defaults.mk
|
||||
|
||||
BIN = ./bin
|
||||
STAGE1_SRC = ./stage1
|
||||
STAGE2_SRC = ./stage2
|
||||
|
||||
STAGE1_SRCS = $(wildcard $(STAGE1_SRC)/*.s)
|
||||
STAGE2_SRCS = $(wildcard $(STAGE2_SRC)/*.c)
|
||||
STAGE2_OBJS = $(patsubst $(STAGE2_SRC)/%.c, $(BIN)/%.o, $(STAGE2_SRCS))
|
||||
|
||||
LINKER = $(STAGE2_SRC)/linker.ld
|
||||
STAGE1 = stage1.bin
|
||||
STAGE2 = stage2.bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(STAGE1) $(STAGE2)
|
||||
|
||||
$(STAGE1): $(STAGE1_SRCS)
|
||||
$(AS) $(ASFLAGS) -fbin -o $@ $(STAGE1_SRC)/bootsect.s
|
||||
|
||||
$(STAGE2): $(STAGE2_OBJS)
|
||||
$(LD) $(LDFLAGS) -T$(LINKER) -o $@ $^
|
||||
|
||||
$(BIN)/%.o: $(STAGE2_SRC)/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -fr $(BIN) $(STAGE1) $(STAGE2)
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
; KBOOT - Kern Bootloader
|
||||
; Most of the code is taken from Limine (https://github.com/limine-bootloader/limine)
|
||||
; I tried to add more documentation than the Limine code had, but it's not everything
|
||||
; Any of my code is pretty bad, so i recommend using an existing bootloader
|
||||
|
||||
[org 0x7c00]
|
||||
[bits 16]
|
||||
|
||||
; BPB Requires these
|
||||
jmp short .bpb_end
|
||||
nop
|
||||
|
||||
; FAT32 Bios Parameter Block
|
||||
; Some BIOSes mess with it so we just leave it blank
|
||||
.bpb:
|
||||
.bpb_oem_id: db "KERN "
|
||||
.bpb_sector_size: dw 0
|
||||
.bpb_sects_per_clust: db 0
|
||||
.bpb_reserved_sects: dw 0
|
||||
.bpb_fat_count: db 0
|
||||
.bpb_root_dir_entries: dw 0
|
||||
.bpb_sector_count: dw 0
|
||||
.bpb_media_type: db 0
|
||||
.bpb_sects_per_fat: dw 0
|
||||
.bpb_sects_per_track: dw 18
|
||||
.bpb_heads_count: dw 2
|
||||
.bpb_hidden_sects: dd 0
|
||||
.bpb_sect_count_big: dd 0
|
||||
; Extended BPB
|
||||
.bpb_drive_num: db 0
|
||||
.bpb_reserved: db 0
|
||||
.bpb_signature: db 0
|
||||
.bpb_volume_id: dd 0
|
||||
.bpb_volume_label: dd "KERN "
|
||||
.bpb_fs_type: times 8 db 0
|
||||
.bpb_end:
|
||||
cli
|
||||
cld
|
||||
jmp 0x0000:.init_codeseg ; Long jump to set CS = 0
|
||||
|
||||
; Zero out segment regs (Because segmentation is shit)
|
||||
.init_codeseg:
|
||||
xor si, si ; We cannot change segment regs directly
|
||||
mov ds, si ; Data Segment
|
||||
mov es, si ; Extra Segment
|
||||
mov ss, si ; Stack Segment
|
||||
mov sp, 0x7c00 ; Set Stack Pointer
|
||||
sti
|
||||
|
||||
; We probably won't be booting from a floppy, so
|
||||
; ignore if boot drive is < 0x80 and assume an error
|
||||
cmp dl, 0x80
|
||||
jl err.0
|
||||
; Also anything above 0x8f is "dubious" so we also
|
||||
; just assume an error
|
||||
cmp dl, 0x8f
|
||||
jg err.1
|
||||
|
||||
; Check that int 13h extensions are supported
|
||||
.int13chk:
|
||||
mov ah, 0x41
|
||||
mov bx, 0x55aa ; Expects bx to be this magic value
|
||||
int 0x13 ; Will se CF if unsupported
|
||||
jc err.2
|
||||
cmp bx, 0xaa55 ; Also sets bx to this magic
|
||||
jne err.3
|
||||
|
||||
; Load the stage 2 bootloader code to 0x70000
|
||||
.load_stage2:
|
||||
mov eax, 1 ; LBA
|
||||
mov cx, 20 ; Read 20 sectors (we have space for 2048)
|
||||
|
||||
; Destination - 0x70000
|
||||
push 0x7000
|
||||
pop es
|
||||
xor bx, bx
|
||||
|
||||
call read_sectors
|
||||
jc err.4 ; Failed to read stage 2
|
||||
|
||||
.enable_protected:
|
||||
; Load GDT Pointer
|
||||
lgdt [gdtp]
|
||||
|
||||
; Set PE (Protected mode Enable) flag
|
||||
cli
|
||||
mov eax, cr0
|
||||
or eax, 1 ; Bit 1 - PE
|
||||
mov cr0, eax
|
||||
|
||||
; Far jump to protected mode
|
||||
jmp code_seg:vector
|
||||
|
||||
%include "stage1/disk.s" ; Disk I/O helper functions
|
||||
%include "stage1/gdt.s" ; Global Descriptor Table
|
||||
|
||||
; Handles an error
|
||||
err:
|
||||
; Error codes
|
||||
.4: inc si ; Failed to read stage2 from disk
|
||||
.3: inc si ; Int 13h extensions unsupported (BX wasn't magic)
|
||||
.2: inc si ; Int 13h extensions unsupported (CF was set)
|
||||
.1: inc si ; Invalid boot drive number (> 0x8f)
|
||||
.0: ; Invalid boot drive number (< 0x80)
|
||||
; Common error handler
|
||||
add si, '0' | (0x4f << 8) ; Store error code number char in SI, white on red
|
||||
push 0xb800 ; VGA Text mode video memory
|
||||
pop es ; ES = 0xb800
|
||||
mov word [es:0], si ; Write character
|
||||
|
||||
; Hang
|
||||
sti
|
||||
.h: hlt
|
||||
jmp .h
|
||||
|
||||
[bits 32]
|
||||
; Protected mode entry vector
|
||||
vector:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
and edx, 0xff ; Still should be boot drive number
|
||||
|
||||
; Call stage 2 bootloader
|
||||
call code_seg:0x70000
|
||||
|
||||
; Padding and boot signature
|
||||
times 510-($-$$) db 0
|
||||
dw 0xaa55
|
||||
@@ -1,26 +0,0 @@
|
||||
; Reads sectors from disk
|
||||
; eax - LBA
|
||||
; cx - Sector count
|
||||
; dl - Drive number
|
||||
; es:dx - Destination
|
||||
read_sectors:
|
||||
pusha
|
||||
|
||||
; Fill out Disk Address Packet
|
||||
mov si, .da_packet
|
||||
mov word [si], 0x10 ; Packet Size and Unused
|
||||
mov word [si+2], cx ; Sector count
|
||||
mov word [si+4], bx ; Dest. offset
|
||||
mov word [si+6], es ; Dest. segment
|
||||
mov dword [si+8], eax ; LBA
|
||||
|
||||
mov ah, 0x42 ; Extended read
|
||||
clc ; Clear CF
|
||||
int 0x13
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; Disk Address Packet
|
||||
.da_packet: equ 0x8000
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
; Global Descriptor Table
|
||||
gdt:
|
||||
.null_desc: ; Just zeros, no clue why it even exists
|
||||
dq 0
|
||||
.code_desc: ; 32-bit code
|
||||
dw 0xffff ; Limit (low 16-bits)
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 0b10011011 ; Access flags
|
||||
db 0b11001111 ; Low 4 bits - Granularity, High 4 bits - Limit (high 4 bits)
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
.data_desc: ; 32-bit data
|
||||
dw 0xffff ; Limit (low 16-bits)
|
||||
dw 0x0000 ; Base (low 16 bits)
|
||||
db 0x00 ; Base (mid 8 bits)
|
||||
db 0b10010011 ; Access flags
|
||||
db 0b11001111 ; Low 4 bits - Granularity, High 4 bits - Limit (high 4 bits)
|
||||
db 0x00 ; Base (high 8 bits)
|
||||
.end:
|
||||
|
||||
; GDT Pointer
|
||||
gdtp:
|
||||
dw gdt.end - gdt - 1 ; Size
|
||||
dd gdt ; Pointer
|
||||
|
||||
; Segments
|
||||
code_seg: equ gdt.code_desc - gdt
|
||||
data_seg: equ gdt.data_desc - gdt
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef _DEFS_H
|
||||
#define _DEFS_H
|
||||
|
||||
#define __packed __attribute__((packed))
|
||||
#define __naked __attribute__((naked))
|
||||
#define __section(_sect) __attribute__((section(_sect)))
|
||||
#define noreturn __attribute__((noreturn))
|
||||
#define sizeof_array(_a) (sizeof(_a) / sizeof(_a[0]))
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "stdint.h"
|
||||
#include "port.h"
|
||||
#include "disk.h"
|
||||
|
||||
void readSectors(uint32_t lba, size_t count, void* dst) {
|
||||
outb(PIO_PORT + 6, ((lba >> 24) & 0x0f) | 0xe0);
|
||||
outb(PIO_PORT + 2, count);
|
||||
outb(PIO_PORT + 3, lba & 0xff);
|
||||
outb(PIO_PORT + 4, (lba >> 8) & 0xff);
|
||||
outb(PIO_PORT + 5, (lba >> 16) & 0xff);
|
||||
outb(PIO_PORT + 7, PIO_CMD_READ);
|
||||
|
||||
uint16_t* buf = (uint16_t*)dst;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
while (inb(PIO_PORT + 7) & (1 << 7)); // Wait until BSY is cleared
|
||||
for (size_t j = 0; j < SECTOR_SIZE / 2; j++) *buf++ = inw(PIO_PORT);
|
||||
for (uint8_t wait = 0; wait < 4; wait++) inb(PIO_ALT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
void writeSectors(uint32_t lba, size_t count, void* src) {
|
||||
outb(PIO_PORT + 6, ((lba >> 24) & 0x0f) | 0xe0);
|
||||
outb(PIO_PORT + 2, count);
|
||||
outb(PIO_PORT + 3, lba & 0xff);
|
||||
outb(PIO_PORT + 4, (lba >> 8) & 0xff);
|
||||
outb(PIO_PORT + 5, (lba >> 16) & 0xff);
|
||||
outb(PIO_PORT + 7, PIO_CMD_WRITE);
|
||||
|
||||
uint16_t* buf = (uint16_t*)src;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
while (inb(PIO_PORT + 7) & (1 << 7)); // Wait until BSY is cleared
|
||||
for (size_t j = 0; j < SECTOR_SIZE / 2; j++) outw(PIO_PORT, *buf++);
|
||||
for (uint8_t wait = 0; wait < 4; wait++) inb(PIO_ALT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef DISK_H
|
||||
#define DISK_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "defs.h"
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define PIO_PORT 0x1f0
|
||||
#define PIO_ALT_STATUS 0x3f6
|
||||
#define PIO_MASTER 0xa0
|
||||
#define PIO_CMD_READ 0x20
|
||||
#define PIO_CMD_WRITE 0x30
|
||||
#define PIO_CMD_FLUSH 0 // TODO
|
||||
|
||||
#define BOOTABLE 0x80
|
||||
|
||||
#define LBA_TO_OFFSET(_a) ((_a) * SECTOR_SIZE)
|
||||
|
||||
struct partition {
|
||||
uint8_t bootable;
|
||||
uint8_t startCHS[3];
|
||||
uint8_t type;
|
||||
uint8_t endCHS[3];
|
||||
uint32_t startLBA;
|
||||
uint32_t size;
|
||||
} __packed;
|
||||
|
||||
struct MBR {
|
||||
uint8_t bootstrap[446];
|
||||
struct partition partitions[4];
|
||||
uint16_t signature;
|
||||
} __packed;
|
||||
|
||||
void readSectors(uint32_t lba, size_t count, void* buffer);
|
||||
void writeSectors(uint32_t lba, size_t count, void* buffer);
|
||||
|
||||
#endif
|
||||
@@ -1,115 +0,0 @@
|
||||
#include "stdint.h"
|
||||
#include "fat32.h"
|
||||
#include "stdio.h"
|
||||
#include "defs.h"
|
||||
#include "disk.h"
|
||||
#include "menu.h"
|
||||
#include "kbd.h"
|
||||
|
||||
noreturn void panic() {
|
||||
setAttr(0x04);
|
||||
text(COLS/2, ROWS/2, "[ PANIC ]");
|
||||
while (1) __asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
void drawPartitions(struct MBR* mbr, uint8_t sel);
|
||||
void partitonInfo(struct partition* part);
|
||||
struct partition* menu(struct MBR* mbr);
|
||||
|
||||
__section("entry")
|
||||
noreturn void main() {
|
||||
keyboardInit();
|
||||
struct MBR mbr;
|
||||
readSectors(0, 1, &mbr);
|
||||
struct partition* bootpart = menu(&mbr);
|
||||
|
||||
setAttr(0x0f);
|
||||
cls();
|
||||
showCursor();
|
||||
|
||||
if (fat32_init(bootpart) != 0) {
|
||||
setAttr(0x0c);
|
||||
printf("Failed to initialize FAT32.");
|
||||
panic();
|
||||
}
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
struct partition* menu(struct MBR* mbr) {
|
||||
// Select bootable partition by default
|
||||
uint8_t selected = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (mbr->partitions[i].bootable != BOOTABLE) continue;
|
||||
selected = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Initial draw
|
||||
setAttr(0x0f);
|
||||
cls();
|
||||
hideCursor();
|
||||
rect(0, 0, COLS, ROWS);
|
||||
hline(0, 2, COLS);
|
||||
setAttr(0x02);
|
||||
text(COLS / 2, 1, "KBOOT");
|
||||
drawPartitions(mbr, selected);
|
||||
partitonInfo(&mbr->partitions[selected]);
|
||||
|
||||
while (1) {
|
||||
// Check for up/down arrow keys or enter
|
||||
uint8_t scancode = getScancode();
|
||||
if (scancode == SC_ENTER) { // Boot selected
|
||||
if (mbr->partitions[selected].type != 0) break;
|
||||
|
||||
// Don't allow booting an unused partition
|
||||
setAttr(0x4f);
|
||||
text(COLS / 2, ROWS / 2 + 6, "Unused Partition");
|
||||
} else if (scancode != SC_EXTENDED) continue; // Not an arrow key
|
||||
|
||||
scancode = getScancode();
|
||||
if (scancode == SCE_ARROW_UP) selected--;
|
||||
else if (scancode == SCE_ARROW_DOWN) selected++;
|
||||
else continue;
|
||||
|
||||
if (selected == 0xff) selected = 3;
|
||||
else if (selected == 4) selected = 0;
|
||||
|
||||
// Redraw
|
||||
drawPartitions(mbr, selected);
|
||||
partitonInfo(&mbr->partitions[selected]);
|
||||
}
|
||||
|
||||
return &mbr->partitions[selected];
|
||||
}
|
||||
|
||||
void drawPartitions(struct MBR* mbr, uint8_t sel) {
|
||||
uint32_t basey = ROWS / 2 - 2;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (i == sel) setAttr(0xf0);
|
||||
else if (mbr->partitions[i].type == 0) setAttr(0x04);
|
||||
else setAttr(0x0f);
|
||||
|
||||
text(COLS / 2, basey + i, " [ Partition %d ] ", i+1);
|
||||
}
|
||||
}
|
||||
|
||||
void partitonInfo(struct partition* part) {
|
||||
uint32_t basey = ROWS / 2 + 6;
|
||||
setAttr(0x02);
|
||||
|
||||
// Clear previous text
|
||||
fill(1, basey, COLS - 2, 3, '\0');
|
||||
|
||||
if (part->type == 0) {
|
||||
text(COLS / 2, basey, "Unused Partition");
|
||||
return;
|
||||
}
|
||||
|
||||
text(COLS / 2, basey, "Type: %02x%s", part->type,
|
||||
(part->bootable == BOOTABLE) ? " Bootable" : "");
|
||||
text(COLS / 2, basey + 1, "Start LBA: %d; End LBA: %d",
|
||||
part->startLBA, part->startLBA + part->size);
|
||||
text(COLS / 2, basey + 2, "Length: 0x%x", part->size);
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "disk.h"
|
||||
#include "fat32.h"
|
||||
|
||||
// Local context
|
||||
struct fat32_ctx ctx;
|
||||
|
||||
int fat32_init(struct partition* p) {
|
||||
readSectors(p->startLBA, 1, &ctx.bpb);
|
||||
ctx.offsetBase = p->startLBA;
|
||||
|
||||
if (ctx.bpb.bytesPerSect != SECTOR_SIZE) return 1;
|
||||
|
||||
ctx.offsetFats = ctx.offsetBase + ctx.bpb.reservedSects;
|
||||
ctx.offsetClusts = ctx.offsetFats + ctx.bpb.fatCount * ctx.bpb.sectsPerFat_32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fat32_open(char* filename, int flags, ...) {
|
||||
// TODO: flags
|
||||
|
||||
//struct fat32_traversed res = fat32_traverse(ctx, filename);
|
||||
//if (!res.dir) return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void fat32_close(void* file) {}
|
||||
|
||||
int fat32_read(const void* buf, size_t size, size_t count, void* file) {}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#ifndef _FAT32_H
|
||||
#define _FAT32_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "defs.h"
|
||||
#include "disk.h"
|
||||
|
||||
// Macros
|
||||
#define FAT32_PTR(_p) ((struct fat32_ctx*)(_p))
|
||||
#define FAT32_DIR_PTR(_p) ((struct fat32_fd*)(_p))
|
||||
#define FAT32_FULL_CLUST(_hi, _lo) (((uint32_t)(_hi) << 16) | (_lo))
|
||||
#define FAT32_INODE_GEN(_dir, _i) ((_dir) * 100 + (_i))
|
||||
|
||||
// Long File Name (LFN)
|
||||
#define LFN_MAX 20
|
||||
#define LFN_MAX_CHARS 256
|
||||
|
||||
// Attributes
|
||||
#define FAT32_ATTR_READ_ONLY (1 << 0)
|
||||
#define FAT32_ATTR_HIDDEN (1 << 1)
|
||||
#define FAT32_ATTR_SYSTEM (1 << 2)
|
||||
#define FAT32_ATTR_VOLUME_ID (1 << 3)
|
||||
#define FAT32_ATTR_DIRECTORY (1 << 4)
|
||||
#define FAT32_ATTR_ARCHIVE (1 << 5)
|
||||
#define FAT32_ATTR_LFN \
|
||||
(FAT32_ATTR_READ_ONLY | FAT32_ATTR_HIDDEN \
|
||||
FAT32_ATTR_SYSTEM | FAT32_ATTR_VOLUME_ID)
|
||||
|
||||
/* On-disk structures */
|
||||
|
||||
// FAT32 Bios Parameter Block & Extended BPB
|
||||
struct fat32_bpb {
|
||||
uint8_t bootjmp[3];
|
||||
char oemName[8];
|
||||
uint16_t bytesPerSect;
|
||||
uint8_t sectsPerClust;
|
||||
uint16_t reservedSects;
|
||||
uint8_t fatCount;
|
||||
uint16_t rootEntryCount;
|
||||
uint16_t totalSects_16;
|
||||
uint8_t mediaType;
|
||||
uint16_t sectsPerFat_16;
|
||||
uint16_t sectsPerTrack;
|
||||
uint16_t headCount;
|
||||
uint32_t hiddenSects;
|
||||
uint32_t sectCount_32;
|
||||
// Extended
|
||||
uint32_t sectsPerFat_32;
|
||||
uint16_t flags;
|
||||
uint16_t fatVersion;
|
||||
uint32_t rootClust;
|
||||
uint16_t fsinfoSect;
|
||||
uint16_t backupBootsect;
|
||||
uint8_t _reserved[12];
|
||||
uint8_t driveNum;
|
||||
uint8_t winNTFlags;
|
||||
uint8_t signature;
|
||||
uint32_t volumeID;
|
||||
char volumeLabel[11];
|
||||
char systemID[8];
|
||||
uint8_t bootcode[420];
|
||||
uint16_t bootsig;
|
||||
} __packed;
|
||||
|
||||
// FAT32 Directory Entry
|
||||
struct fat32_dentry {
|
||||
char name[8];
|
||||
char ext[3];
|
||||
uint8_t attr;
|
||||
uint8_t userattr;
|
||||
char undelete;
|
||||
uint16_t createTime;
|
||||
uint16_t createDate;
|
||||
uint16_t accessDate;
|
||||
uint16_t clustHigh;
|
||||
uint16_t modifyTime;
|
||||
uint16_t modifyDate;
|
||||
uint16_t clustLow;
|
||||
uint32_t size;
|
||||
} __packed;
|
||||
|
||||
// FAT32 Long File Name entry
|
||||
struct fat32_lfn {
|
||||
uint8_t order;
|
||||
uint8_t name1[10];
|
||||
uint8_t attr;
|
||||
uint8_t type;
|
||||
uint8_t checksum;
|
||||
uint8_t name2[12];
|
||||
uint16_t zero;
|
||||
uint8_t name3[4];
|
||||
} __packed;
|
||||
|
||||
/* In memory structures */
|
||||
struct fat32_ctx {
|
||||
size_t offsetBase;
|
||||
size_t offsetFats;
|
||||
size_t offsetClusts;
|
||||
|
||||
struct fat32_bpb bpb;
|
||||
};
|
||||
|
||||
struct fat32_fd {
|
||||
uint32_t ptr;
|
||||
uint8_t index;
|
||||
uint32_t dirStart;
|
||||
uint32_t dirCurrent;
|
||||
struct fat32_dentry dentry;
|
||||
};
|
||||
|
||||
// Handlers
|
||||
int fat32_init(struct partition* p);
|
||||
int fat32_open(char* filename, int flags, ...); /* We won't use the va_args */
|
||||
|
||||
|
||||
void* fat32_fopen(const char* path, const char* mode);
|
||||
void fat32_fclose(void* file);
|
||||
int fat32_fgetc(void* file);
|
||||
char* fat32_fgets(char* s, size_t n, void* file);
|
||||
int fat32_fread(const void* buf, size_t size, size_t count, void* file);
|
||||
int fat32_fseek(void* file, size_t offset, int whence);
|
||||
long fat32_ftell(void* file);
|
||||
|
||||
#endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "stdint.h"
|
||||
#include "port.h"
|
||||
#include "kbd.h"
|
||||
|
||||
// TODO: Maybe do some setup?
|
||||
int keyboardInit() { return 0; }
|
||||
|
||||
uint8_t getScancode() {
|
||||
while ((inb(PS2_STAT_PORT) & 0x01) == 0);
|
||||
return inb(PS2_DATA_PORT);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef _KBD_H
|
||||
#define _KBD_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#define PS2_DATA_PORT 0x60
|
||||
#define PS2_STAT_PORT 0x64
|
||||
|
||||
// Scancodes
|
||||
#define SC_ENTER 0x1C
|
||||
#define SC_EXTENDED 0xE0
|
||||
// Extended scancodes
|
||||
#define SCE_ARROW_UP 0x48
|
||||
#define SCE_ARROW_DOWN 0x50
|
||||
|
||||
int keyboardInit();
|
||||
uint8_t getScancode();
|
||||
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x70000;
|
||||
|
||||
.text : {
|
||||
*(entry)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data : {
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#include "stdarg.h"
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "menu.h"
|
||||
|
||||
/*
|
||||
* The reason we subtract one from the width and height (or length) is because
|
||||
* we use the (in this example) width to offset from the (in this example) x
|
||||
* position. If something has a width of 1 character, the end of it should be
|
||||
* at 'x + w', so if 'w' were 1, it would be off by one. Therefore we subtract
|
||||
* one from the given dimensions.
|
||||
*/
|
||||
|
||||
void rect(uint32_t x, uint32_t y, uint32_t _w, uint32_t _h) {
|
||||
if (_w < 2 || _h < 2) return;
|
||||
uint32_t w = _w - 1;
|
||||
uint32_t h = _h - 1;
|
||||
|
||||
// Top
|
||||
putat(y, x, CORNER_TL);
|
||||
for (size_t dx = 1; dx < w; dx++) putat(y, x + dx, LINE_H);
|
||||
putat(y, x + w, CORNER_TR);
|
||||
|
||||
// Sides
|
||||
for (size_t dy = 1; dy < h; dy++) {
|
||||
putat(y + dy, x, LINE_V);
|
||||
putat(y + dy, x + w, LINE_V);
|
||||
}
|
||||
|
||||
// Bottom
|
||||
putat(y + h, x, CORNER_BL);
|
||||
for (size_t dx = 1; dx < w; dx++) putat(y + h, x + dx, LINE_H);
|
||||
putat(y + h, x + w, CORNER_BR);
|
||||
}
|
||||
|
||||
void fill(uint32_t x, uint32_t y, uint32_t w, uint32_t h, char c) {
|
||||
// We don't add one to the dimensions here
|
||||
for (size_t dy = 0; dy < h; dy++) {
|
||||
for (size_t dx = 0; dx < w; dx++) {
|
||||
putat(y + dy, x + dx, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hline(uint32_t x, uint32_t y, uint32_t _len) {
|
||||
uint32_t len = _len - 1;
|
||||
putat(y, x, LINE_T_RIGHT);
|
||||
for (size_t dx = 1; dx < len; dx++) putat(y, x + dx, LINE_H);
|
||||
putat(y, x + len, LINE_T_LEFT);
|
||||
}
|
||||
|
||||
void vline(uint32_t x, uint32_t y, uint32_t _len) {
|
||||
uint32_t len = _len - 1;
|
||||
putat(y, x, LINE_T_DOWN);
|
||||
for (size_t dy = 1; dy < len; dy++) putat(y + dy, x, LINE_V);
|
||||
putat(y + len, x, LINE_T_UP);
|
||||
}
|
||||
|
||||
void text(uint32_t x, uint32_t y, char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char buf[256];
|
||||
vsnprintf(buf, 256, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
uint32_t len = strlen(buf);
|
||||
uint32_t basex = x - len / 2;
|
||||
|
||||
size_t i = 0;
|
||||
while (buf[i] != '\0') putat(y, basex + i, buf[i++]);
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef _MENU_H
|
||||
#define _MENU_H
|
||||
|
||||
// Box drawing characters
|
||||
#define SHADE_LIGHT 0xB0
|
||||
#define SHADE_MEDIUM 0xB1
|
||||
#define SHADE_DARK 0xB2
|
||||
#define LINE_V 0xB3
|
||||
#define LINE_T_LEFT 0xB4
|
||||
#define CORNER_TR 0xBF
|
||||
#define CORNER_BL 0xC0
|
||||
#define LINE_T_UP 0xC1
|
||||
#define LINE_T_DOWN 0xC2
|
||||
#define LINE_T_RIGHT 0xC3
|
||||
#define LINE_H 0xC4
|
||||
#define LINE_CROSS 0xC5
|
||||
#define CORNER_BR 0xD9
|
||||
#define CORNER_TL 0xDA
|
||||
#define BLOCK 0xDB
|
||||
#define BLOCK_UPPER 0xDC
|
||||
#define BLOCK_LEFT 0xDD
|
||||
#define BLOCK_RIGHT 0xDE
|
||||
#define BLOCK_LOWER 0xDF
|
||||
#define INT_UPPER 0xF4
|
||||
#define INT_LOWER 0xF5
|
||||
|
||||
void rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
void fill(uint32_t x, uint32_t y, uint32_t w, uint32_t h, char c);
|
||||
void hline(uint32_t x, uint32_t y, uint32_t len);
|
||||
void vline(uint32_t x, uint32_t y, uint32_t len);
|
||||
void text(uint32_t x, uint32_t y, char* fmt, ...);
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
inline uint8_t inb(uint16_t port) {
|
||||
uint8_t result;
|
||||
__asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
inline void outb(uint16_t port, uint8_t data) {
|
||||
__asm__ volatile("outb %0, %1" :: "a"(data), "Nd"(port));
|
||||
}
|
||||
|
||||
inline uint16_t inw(uint16_t port) {
|
||||
uint16_t result;
|
||||
__asm__ volatile("inw %1, %0" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
inline void outw(uint16_t port, uint16_t data) {
|
||||
__asm__ volatile("outw %0, %1" :: "a"(data), "Nd"(port));
|
||||
}
|
||||
|
||||
inline uint32_t inl(uint16_t port) {
|
||||
uint32_t result;
|
||||
__asm__ volatile("inl %1, %0" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
inline void outl(uint16_t port, uint32_t data) {
|
||||
__asm__ volatile("outl %0, %1" :: "a"(data), "Nd"(port));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef char* va_list;
|
||||
#define va_start(ap, paramn) (void)((ap) = (char*)(&(paramn) + 1))
|
||||
#define va_end(ap) (void)((ap) = 0)
|
||||
#define va_arg(ap, type) (((type*)((ap) = ((ap) + sizeof(type))))[-1])
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
// Naitive size
|
||||
typedef unsigned int size_t;
|
||||
typedef signed int ssize_t;
|
||||
|
||||
// Signed ints
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
// Unsigned ints
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif
|
||||
@@ -1,143 +0,0 @@
|
||||
#include "stdarg.h"
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "port.h"
|
||||
|
||||
static uint32_t xpos;
|
||||
static uint32_t ypos;
|
||||
static uint8_t attr;
|
||||
|
||||
void setAttr(uint8_t newattr) { attr = newattr; }
|
||||
|
||||
void setCursor(uint32_t row, uint32_t col) {
|
||||
xpos = col;
|
||||
ypos = row;
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
void updateCursor() {
|
||||
uint16_t pos = xpos + ypos * COLS;
|
||||
|
||||
outb(0x3d4, 0x0f);
|
||||
outb(0x3d5, pos & 0xff);
|
||||
outb(0x3d4, 0x0e);
|
||||
outb(0x3d5, (pos >> 8) & 0xff);
|
||||
}
|
||||
|
||||
void hideCursor() {
|
||||
outb(0x3d4, 0x0a);
|
||||
outb(0x3d5, 0x20);
|
||||
}
|
||||
|
||||
void showCursor() {
|
||||
uint8_t start = 0;
|
||||
uint8_t end = 15;
|
||||
|
||||
outb(0x3d4, 0x0a);
|
||||
outb(0x3d5, (inb(0x3d5) & 0xc0) | start);
|
||||
outb(0x3d4, 0x0b);
|
||||
outb(0x3d5, (inb(0x3d5) & 0xe0) | end);
|
||||
}
|
||||
|
||||
void cls() {
|
||||
uint8_t* vidmem = (uint8_t*)VIDMEM;
|
||||
|
||||
for (size_t i = 0; i < ROWS * COLS; i++) {
|
||||
vidmem[i * 2] = 0;
|
||||
vidmem[i * 2 + 1] = attr;
|
||||
}
|
||||
|
||||
xpos = 0;
|
||||
ypos = 0;
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
void putat(uint32_t row, uint32_t col, int c) {
|
||||
uint8_t* vidmem = (uint8_t*)VIDMEM;
|
||||
vidmem[(col + row * COLS) * 2] = c & 0xFF;
|
||||
vidmem[(col + row * COLS) * 2 + 1] = attr;
|
||||
}
|
||||
|
||||
void newline() {
|
||||
xpos = 0;
|
||||
ypos++;
|
||||
if (ypos >= ROWS) ypos = 0;
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
void putc(int c) {
|
||||
putat(ypos, xpos, c);
|
||||
xpos++;
|
||||
if (xpos >= COLS) newline();
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
void puts(char* s) {
|
||||
while (*s != '\0') {
|
||||
if (*s == '\n' || *s == '\r') {
|
||||
newline();
|
||||
s++;
|
||||
} else putc(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
int vsnprintf(void* buf, size_t len, char* fmt, va_list args) {
|
||||
char* str = (char*)buf;
|
||||
size_t pos = 0;
|
||||
|
||||
while (*fmt != '\0') {
|
||||
if (*fmt != '%') {
|
||||
if (pos < len - 1) str[pos++] = *fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fmt++;
|
||||
char pad = ' ';
|
||||
int width = 0;
|
||||
|
||||
if (*fmt == '0') pad = '0';
|
||||
while (*fmt >= '0' && *fmt <= '9') {
|
||||
width *= 10;
|
||||
width += *fmt++ - '0';
|
||||
}
|
||||
|
||||
// DO NOT TALK ABOUT THIS ABOMINATION
|
||||
char* s;
|
||||
switch (*fmt++) {
|
||||
case 'd': s = itoa(va_arg(args, int), 10); goto string;
|
||||
case 'x': s = itoa(va_arg(args, int), 16); goto string;
|
||||
case 's': s = va_arg(args, char*); goto string;
|
||||
case 'c': if (pos < len - 1) str[pos++] = va_arg(args, char); break;
|
||||
case '%': if (pos < len - 1) str[pos++] = '%'; break;
|
||||
default:
|
||||
if (pos < len - 1) str[pos++] = '%';
|
||||
if (pos < len - 1) str[pos++] = *(fmt - 1);
|
||||
break;
|
||||
string:
|
||||
width -= strlen(s) - 1;
|
||||
if (width < 0) width = 0;
|
||||
while (width-- && pos < len - 1) str[pos++] = pad;
|
||||
while (*s && pos < len - 1) str[pos++] = *s++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (pos < len) str[pos++] = '\0';
|
||||
else str[len - 1] = '\0'; // Shouldn't be able to be reached, but who knows
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int printf(char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char buf[256];
|
||||
int ret = vsnprintf(buf, 256, fmt, args);
|
||||
va_end(args);
|
||||
puts(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
|
||||
#include "stdarg.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#define VIDMEM 0xb8000
|
||||
#define COLS 80
|
||||
#define ROWS 25
|
||||
|
||||
void setAttr(uint8_t attr);
|
||||
void setCursor(uint32_t row, uint32_t col);
|
||||
void updateCursor();
|
||||
void hideCursor();
|
||||
void showCursor();
|
||||
|
||||
void cls();
|
||||
void newline();
|
||||
void putc(int c);
|
||||
void puts(char* s);
|
||||
int printf(char* fmt, ...);
|
||||
int vsnprintf(void* buf, size_t len, char* fmt, va_list args);
|
||||
void putat(uint32_t row, uint32_t col, int c);
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
|
||||
char* itoa(size_t val, int base) {
|
||||
static char buf[32] = { 0 };
|
||||
|
||||
if (base == 0 || base > 16) return NULL;
|
||||
|
||||
if (val == 0) {
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int i;
|
||||
buf[31] = '\0';
|
||||
for (i = 30; val && i; i--, val /= base) {
|
||||
buf[i] = "0123456789abcdef"[val % base];
|
||||
}
|
||||
|
||||
return &buf[i + 1];
|
||||
}
|
||||
|
||||
void* memcpy(void* src, void* dst, size_t length) {
|
||||
uint8_t* p = dst;
|
||||
size_t i = 0;
|
||||
while (i < length) p[i] = *(uint8_t*)(src + i);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void* memset(void* dst, uint8_t val, size_t length) {
|
||||
uint8_t* p = dst;
|
||||
size_t i = 0;
|
||||
while (i < length) p[i++] = val;
|
||||
return dst;
|
||||
}
|
||||
|
||||
char* strcpy(char* str1, const char* str2) {
|
||||
char* p = str1;
|
||||
while (*str2 != '\0') *p++ = *str2++;
|
||||
return str1;
|
||||
}
|
||||
|
||||
char* strcat(char* str1, const char* str2) {
|
||||
char* p = str1;
|
||||
while (*str2++ != '\0');
|
||||
while (*str2 != '\0') *p++ = *str2++;
|
||||
return str1;
|
||||
}
|
||||
|
||||
char* strchr(const char* str, char c) {
|
||||
char* p = (char*)str;
|
||||
while (*p != '\0' && *p != c) p++;
|
||||
return (*p == c) ? p : NULL;
|
||||
}
|
||||
|
||||
int strcmp(const char* str1, const char* str2) {
|
||||
while (*str1 != '\0' && *str1 == *str2) {
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
|
||||
uint8_t c1 = (*(uint8_t*)str1);
|
||||
uint8_t c2 = (*(uint8_t*)str2);
|
||||
|
||||
return ((c1 < c2) ? -1 : (c1 > c2));
|
||||
}
|
||||
|
||||
size_t strlen(const char* str) {
|
||||
size_t len = 0;
|
||||
while (str[len++] != '\0');
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
char* itoa(size_t val, int base);
|
||||
void* memcpy(void* src, void* dst, size_t length);
|
||||
void* memset(void* dst, uint8_t value, size_t length);
|
||||
char* strcpy(char* str1, const char* str2);
|
||||
char* strcat(char* str1, const char* str2);
|
||||
char* strchr(const char* str, char c);
|
||||
int strcmp(const char* str1, const char* str2);
|
||||
size_t strlen(const char* str);
|
||||
|
||||
#endif
|
||||
+7
-7
@@ -1,17 +1,17 @@
|
||||
# Tools
|
||||
HOSTCC = cc
|
||||
CC = i686-elf-gcc
|
||||
LD = i686-elf-ld
|
||||
CC = cc
|
||||
LD = ld
|
||||
AS = nasm
|
||||
AR = i686-elf-ar
|
||||
OBJCOPY = i686-elf-objcopy
|
||||
AR = ar
|
||||
OBJCOPY = objcopy
|
||||
MAKE = make
|
||||
|
||||
# Flags
|
||||
HOSTCFLAGS = -Wall -Wextra -Wpedantic -Os -std=c17 -g
|
||||
CFLAGS = -Wall -Wextra -Wpedantic -Wno-pointer-arith\
|
||||
HOSTCCFLAGS = -Wall -Wextra -Wpedantic -Os -std=c17
|
||||
CCFLAGS = -Wall -Wextra -Wpedantic -Wno-pointer-arith\
|
||||
-ffreestanding -fno-stack-protector -fno-builtin -fno-pie -fcommon\
|
||||
-O2 -std=c17 -nostdinc -nostdlib -z notext -march=i386 -g
|
||||
-O2 -std=c17 -nostdinc -nostdlib -z notext -march=i386 -m32
|
||||
LDFLAGS = -melf_i386
|
||||
ASFLAGS =
|
||||
ARFLAGS =
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _KERNEL_H
|
||||
#define _KERNEL_H
|
||||
|
||||
/*
|
||||
* Attribute definitions
|
||||
*/
|
||||
#define __align(_b) __attribute__((aligned(_b)))
|
||||
#define __depricated __attribute__((depricated))
|
||||
#define __packed __attribute__((packed))
|
||||
#define __noreturn __attribute__((noreturn))
|
||||
#define __const __attribute__((const))
|
||||
#define __pure __attribute__((pure))
|
||||
#define __inline __attribute__((always_inline))
|
||||
#define __no_inline __attribute__((never_inline))
|
||||
#define __section(_s) __attribute__((section(_s)))
|
||||
#define __cold __attribute__((cold))
|
||||
#define __hot __attribute__((hot))
|
||||
#define __naked __attribute__((naked))
|
||||
|
||||
/*
|
||||
* Utility macros
|
||||
*/
|
||||
#define sizeof_array(_a) ()
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
// Naitive size
|
||||
typedef unsigned int size_t;
|
||||
typedef signed int ssize_t;
|
||||
|
||||
// Signed ints
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
// Unsigned ints
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _TTY_H
|
||||
#define _TTY_H
|
||||
|
||||
int tty_init(void);
|
||||
int tty_write(char* buf, size_t len);
|
||||
int tty_putc(char c);
|
||||
int tty_puts(char* s);
|
||||
|
||||
#endif
|
||||
+13
-34
@@ -1,52 +1,31 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
ENTRY(start)
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x00100000;
|
||||
kernel_start = .;
|
||||
/* 1MB is a conventional place for kernels */
|
||||
. = 1M;
|
||||
|
||||
/* Multiboot Header */
|
||||
.multiboot ALIGN(4K) : {
|
||||
/* We need the multiboot header in the first 8192 bytes */
|
||||
.text BLOCK(4K) : ALIGN(4K) {
|
||||
*(.multiboot)
|
||||
}
|
||||
|
||||
.boot ALIGN(4K) : {
|
||||
*(.boot)
|
||||
}
|
||||
|
||||
. += 0xC000000;
|
||||
|
||||
/* Kernel Code */
|
||||
.text ALIGN(4) : AT(ADDR(.text) - 0xC000000) {
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
}
|
||||
|
||||
/* Read-Only Data */
|
||||
.rodata ALIGN(4) : AT(ADDR(.rodata) - 0xC000000) {
|
||||
/* Read-only data */
|
||||
.rodata BLOCK(4K) : ALIGN(4K) {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
}
|
||||
|
||||
/* Read/Write Data */
|
||||
.data ALIGN(4) : AT(ADDR(.data) - 0xC000000) {
|
||||
/* Initalized r/w data */
|
||||
.data BLOCK(4K) : ALIGN(4K) {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
}
|
||||
|
||||
/* BSS Section */
|
||||
.bss ALIGN(4) : AT(ADDR(.bss) - 0xC000000) {
|
||||
/* Uninitialized r/w data and stack */
|
||||
.bss BLOCK(4K) : ALIGN(4K) {
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
}
|
||||
|
||||
/* Discarded Sections */
|
||||
/DISCARD/ : {
|
||||
*(.note)
|
||||
*(.note.*)
|
||||
*(.comment)
|
||||
}
|
||||
|
||||
kernel_end = .;
|
||||
. = 4M;
|
||||
}
|
||||
|
||||
+10
-13
@@ -1,30 +1,27 @@
|
||||
include ../defaults.mk
|
||||
|
||||
INC = ./include
|
||||
SRC = ./src
|
||||
BIN = ./bin
|
||||
|
||||
SRCS_C = $(shell find $(SRC) -name '*.c')
|
||||
SRCS_S = $(shell find $(SRC) -name '*.s')
|
||||
OBJS = $(patsubst $(SRC)/%.c, $(BIN)/%.o, $(SRCS_C)) \
|
||||
$(patsubst $(SRC)/%.s, $(BIN)/%.s.o, $(SRCS_S))
|
||||
|
||||
INC = ./include
|
||||
SRCS_C = $(wildcard $(SRC)/*.c)
|
||||
SRCS_S = $(wildcard $(SRC)/*.s)
|
||||
OBJS_C = $(patsubst $(SRC)/%.c, $(BIN)/%.o, $(SRCS_C))
|
||||
OBJS_S = $(patsubst $(SRC)/%.s, $(BIN)/%.o, $(SRCS_S))
|
||||
OUT = ./kernel.elf
|
||||
LINKER = ./linker.ld
|
||||
OUT = ./kern.bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OUT)
|
||||
$(OUT): $(OBJS)
|
||||
$(OUT): $(OBJS_C) $(OBJS_S)
|
||||
$(LD) $(LDFLAGS) -T$(LINKER) -o $@ $^
|
||||
|
||||
$(BIN)/%.o: $(SRC)/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -I$(INC) -c -o $@ $<
|
||||
$(CC) $(CCFLAGS) -I$(INC) -c -o $@ $^
|
||||
|
||||
$(BIN)/%.s.o: $(SRC)/%.s
|
||||
$(BIN)/%.o: $(SRC)/%.s
|
||||
@mkdir -p $(dir $@)
|
||||
$(AS) $(ASFLAGS) -felf32 -o $@ $<
|
||||
$(AS) $(ASFLAGS) -felf32 -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -fr $(BIN) $(OUT)
|
||||
|
||||
+26
-94
@@ -1,108 +1,40 @@
|
||||
;
|
||||
; Kernel entry point
|
||||
;
|
||||
|
||||
MBH_MAGIC equ 0xe85250d6
|
||||
MBH_ARCH equ 0x00000000
|
||||
STACK_SIZE equ 4096
|
||||
global VIRT_BASE
|
||||
KERN_VIRT_BASE equ 0xC000000
|
||||
KERN_PAGE_NUM equ (KERN_VIRT_BASE >> 22)
|
||||
|
||||
bits 32
|
||||
|
||||
; Multiboot2 Header
|
||||
; Flag bits
|
||||
%define ALIGN 1<<0
|
||||
%define MEMINFO 1<<1
|
||||
|
||||
; Field values
|
||||
%define MAGIC 0x1BADB002
|
||||
%define FLAGS (ALIGN | MEMINFO)
|
||||
%define CHECK -(MAGIC + FLAGS)
|
||||
|
||||
; Multiboot 1 header
|
||||
section .multiboot
|
||||
align 64
|
||||
mbh:
|
||||
; Magic fields
|
||||
.magic: dd MBH_MAGIC
|
||||
.arch: dd MBH_ARCH
|
||||
.size: dd (mbh.end - mbh)
|
||||
.checksum: dd 0x10000000 - (MBH_MAGIC + MBH_ARCH + (mbh.end - mbh))
|
||||
align 4
|
||||
multiboot:
|
||||
dd MAGIC
|
||||
dd FLAGS
|
||||
dd CHECK
|
||||
|
||||
; Framebuffer Tag
|
||||
align 8
|
||||
dw 5 ; Type - Framebuffer
|
||||
dw 1 ; Flags - Optional
|
||||
dd 20 ; Size
|
||||
dd 1920 ; Width
|
||||
dd 1080 ; Height
|
||||
dd 32 ; Depth
|
||||
|
||||
; Zero Tag
|
||||
align 8
|
||||
dw 0 ; Type - Zero
|
||||
dw 0 ; Flags
|
||||
dd 8 ; Size
|
||||
|
||||
.end:
|
||||
|
||||
; Stack
|
||||
; Initialize stack
|
||||
section .bss
|
||||
align 16
|
||||
stack_bottom:
|
||||
resb 16384*8
|
||||
resb 16384 ; 16kB
|
||||
stack_top:
|
||||
|
||||
; Entry section
|
||||
section .boot
|
||||
global start
|
||||
|
||||
extern kmain
|
||||
start:
|
||||
; Init temporary paging
|
||||
mov eax, (initpd - 0xC0000000)
|
||||
mov cr3, eax
|
||||
|
||||
mov ecx, cr4
|
||||
or ecx, 0x10 ; Paging enable bit
|
||||
mov cr4, ecx
|
||||
|
||||
mov ecx, cr0
|
||||
or ecx, 0x8000000
|
||||
mov cr0, ecx
|
||||
|
||||
jmp higher_half
|
||||
|
||||
Shutdown:
|
||||
mov ax, 0x1000
|
||||
mov ss, ax
|
||||
mov sp, 0xf000
|
||||
mov ax, 0x5307
|
||||
mov bx, 0x0001
|
||||
mov cx, 0x0003
|
||||
int 0x15
|
||||
|
||||
; Entry point
|
||||
section .text
|
||||
higher_half:
|
||||
mov esp, stack_top ; Stack Pointer
|
||||
global _start
|
||||
extern kmain
|
||||
_start:
|
||||
mov esp, stack_top
|
||||
|
||||
add ebx, KERN_VIRT_BASE ; Make address in EBX virtual
|
||||
push ebx ; Push multiboot mem info pointer
|
||||
call kmain ; Call kernel main
|
||||
|
||||
call kmain
|
||||
|
||||
; Halt on return
|
||||
; Hang if kernel returns
|
||||
cli
|
||||
h: hlt
|
||||
jmp h
|
||||
|
||||
section .data
|
||||
|
||||
; Inital Page Directory
|
||||
align 4096
|
||||
global initpd
|
||||
initpd:
|
||||
dd 0b10000011 ; Initial 4MB identity map
|
||||
|
||||
times 768-1 dd 0 ; Padding
|
||||
|
||||
; Higher half kernel start, map 16MB
|
||||
dd (0 << 22) | 0b10000011
|
||||
dd (1 << 22) | 0b10000011
|
||||
dd (2 << 22) | 0b10000011
|
||||
dd (3 << 22) | 0b10000011
|
||||
|
||||
times 256-4 dd 0 ; More padding
|
||||
.hlt: hlt
|
||||
jmp .hlt
|
||||
|
||||
|
||||
+6
-2
@@ -1,4 +1,8 @@
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
|
||||
void kmain(uint32_t addr) {}
|
||||
__noreturn
|
||||
void kmain(void) {
|
||||
*(char*)0xb8000 = 'a';
|
||||
while (1) __asm__ volatile ("movl $69, %eax");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
#include <ctype.h>
|
||||
|
||||
const unsigned char _CTYPE_TABLE[256] = {
|
||||
// Control characters (ASCII 0-31)
|
||||
_CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, // 0-7
|
||||
_CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, // 8-15
|
||||
_CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, // 16-23
|
||||
_CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, _CNTRL_MASK, // 24-31
|
||||
// Space (ASCII 32)
|
||||
_SPACE_MASK | _PRINT_MASK,
|
||||
// Punctuation (ASCII 33-47)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '!' (ASCII 33)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '"' (ASCII 34)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '#' (ASCII 35)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '$' (ASCII 36)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '%' (ASCII 37)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '&' (ASCII 38)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '\'' (ASCII 39)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '(' (ASCII 40)
|
||||
_PUNCT_MASK | _PRINT_MASK, // ')' (ASCII 41)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '*' (ASCII 42)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '+' (ASCII 43)
|
||||
_PUNCT_MASK | _PRINT_MASK, // ',' (ASCII 44)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '-' (ASCII 45)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '.' (ASCII 46)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '/' (ASCII 47)
|
||||
// Digits (ASCII 48-57)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '0' (ASCII 48)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '1' (ASCII 49)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '2' (ASCII 50)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '3' (ASCII 51)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '4' (ASCII 52)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '5' (ASCII 53)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '6' (ASCII 54)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '7' (ASCII 55)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '8' (ASCII 56)
|
||||
_DIGIT_MASK | _PRINT_MASK, // '9' (ASCII 57)
|
||||
// Punctuation (ASCII 58-64)
|
||||
_PUNCT_MASK | _PRINT_MASK, // ':' (ASCII 58)
|
||||
_PUNCT_MASK | _PRINT_MASK, // ';' (ASCII 59)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '<' (ASCII 60)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '=' (ASCII 61)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '>' (ASCII 62)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '?' (ASCII 63)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '@' (ASCII 64)
|
||||
// Upperchase letters (ASCII 65-90)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'A' (ASCII 65)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'B' (ASCII 66)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'C' (ASCII 67)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'D' (ASCII 68)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'E' (ASCII 69)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'F' (ASCII 70)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'G' (ASCII 71)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'H' (ASCII 72)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'I' (ASCII 73)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'J' (ASCII 74)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'K' (ASCII 75)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'L' (ASCII 76)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'M' (ASCII 77)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'N' (ASCII 78)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'O' (ASCII 79)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'P' (ASCII 80)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'Q' (ASCII 81)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'R' (ASCII 82)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'S' (ASCII 83)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'T' (ASCII 84)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'U' (ASCII 85)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'V' (ASCII 86)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'W' (ASCII 87)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'X' (ASCII 88)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'Y' (ASCII 89)
|
||||
_ALPHA_MASK | _PRINT_MASK, // 'Z' (ASCII 90)
|
||||
// Punctuation (ASCII 91-96)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '[' (ASCII 91)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '\' (ASCII 92)
|
||||
_PUNCT_MASK | _PRINT_MASK, // ']' (ASCII 93)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '^' (ASCII 94)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '_' (ASCII 95)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '`' (ASCII 96)
|
||||
// Lowercase letters (ASCII 97-122)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'a' (ASCII 97)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'b' (ASCII 98)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'c' (ASCII 99)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'd' (ASCII 100)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'e' (ASCII 101)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'f' (ASCII 102)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'g' (ASCII 103)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'h' (ASCII 104)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'i' (ASCII 105)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'j' (ASCII 106)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'k' (ASCII 107)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'l' (ASCII 108)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'm' (ASCII 109)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'n' (ASCII 110)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'o' (ASCII 111)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'p' (ASCII 112)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'q' (ASCII 113)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'r' (ASCII 114)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 's' (ASCII 115)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 't' (ASCII 116)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'u' (ASCII 117)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'v' (ASCII 118)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'w' (ASCII 119)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'x' (ASCII 120)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'y' (ASCII 121)
|
||||
_ALPHA_MASK | _LOWER_MASK | _PRINT_MASK, // 'z' (ASCII 122)
|
||||
// Punctuation (ASCII 123-126
|
||||
_PUNCT_MASK | _PRINT_MASK, // '{' (ASCII 123)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '|' (ASCII 124)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '}' (ASCII 125)
|
||||
_PUNCT_MASK | _PRINT_MASK, // '~' (ASCII 126)
|
||||
// Control character (ASCII 127)
|
||||
_CNTRL_MASK // DEL (ASCII 127)
|
||||
};
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#include <errno.h>
|
||||
|
||||
int errno = 0;
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H
|
||||
|
||||
// TODO:
|
||||
#define assert(_ignore) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H
|
||||
|
||||
/*
|
||||
* Bitfield values
|
||||
*
|
||||
* Property | Bit
|
||||
* ------------|-----
|
||||
* Digit | 0
|
||||
* Letter | 1
|
||||
* Lowercase | 2
|
||||
* Punct | 3
|
||||
* Space | 4
|
||||
* Control | 5
|
||||
* Printable | 6
|
||||
* Hex digit | 7
|
||||
*/
|
||||
#define _DIGIT_MASK (1<<0)
|
||||
#define _ALPHA_MASK (1<<1)
|
||||
#define _LOWER_MASK (1<<2)
|
||||
#define _PUNCT_MASK (1<<3)
|
||||
#define _SPACE_MASK (1<<4)
|
||||
#define _CNTRL_MASK (1<<5)
|
||||
#define _PRINT_MASK (1<<6)
|
||||
#define _HEXDG_MASK (1<<7)
|
||||
|
||||
// A table for the ASCII character set
|
||||
extern const unsigned char _CTYPE_TABLE[256];
|
||||
|
||||
// Just a macro to make this easier
|
||||
#define _CTYPE_CHECK(_c, _mask) (_CTYPE_TABLE[(unsigned char)(_c)] & (_mask))
|
||||
|
||||
#define isalnum(_c) (isalpha((_c)) || isdigit((_c))
|
||||
#define isalpha(_c) _CTYPE_CHECK((_c), _ALPHA_MASK)
|
||||
#define islower(_c) _CTYPE_CHECK((_c), _LOWER_MASK)
|
||||
#define isupper(_c) (!islower((_c)) && isalpha((_c)))
|
||||
#define isdigit(_c) _CTYPE_CHECK((_c), _DIGIT_MASK)
|
||||
#define iscntrl(_c) _CTYPE_CHECK((_c), _CNTRL_MASK)
|
||||
#define isgraph(_c) (!isblank((_c)))
|
||||
#define isspace(_c) _CTYPE_CHECK((_c), _SPACE_MASK)
|
||||
#define isblank(_c) (iscntrl((_c)) || isspace((_c)))
|
||||
#define isprint(_c) _CTYPE_CHECK((_c), _PRINT_MASK)
|
||||
#define ispunct(_c) _CTYPE_CHECK((_c), _PUNCT_MASK)
|
||||
// Why is this one's name longer :((
|
||||
#define isxdigit(_c) _CTYPE_CHECK((_c), _HEXDG_MASK);
|
||||
|
||||
// TODO:
|
||||
// tolower()
|
||||
// toupper()
|
||||
|
||||
#endif
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
|
||||
// Basic POSIX defined error idk
|
||||
enum {
|
||||
EPERM = 1, // Operation not permitted
|
||||
ENOENT, // No such file or directory
|
||||
ESRCH, // No such process
|
||||
EINTR, // Interrupted system call
|
||||
EIO, // I/O error
|
||||
ENXIO, // No such device or address
|
||||
E2BIG, // Argument list too long
|
||||
ENOEXEC, // Exec format error
|
||||
EBADF, // Bad file descriptor
|
||||
ECHILD, // No child processes
|
||||
EAGAIN, // Resource temporarily unavailable
|
||||
ENOMEM, // Out of memory
|
||||
EACCES, // Permission denied
|
||||
EFAULT, // Bad address
|
||||
EBUSY, // Device or resource busy
|
||||
EEXIST, // File exists
|
||||
ENOTDIR, // Not a directory
|
||||
EISDIR, // Is a directory
|
||||
EIMPL, // TODO: Implementation defined
|
||||
ENOMSG, // No message of desired type
|
||||
EINVAL, // Invalid argument
|
||||
ENFILE, // File table overflow
|
||||
EMFILE, // Too many open files
|
||||
ENOTTY, // Not a typewriter
|
||||
ETXTBSY, // Text file busy
|
||||
EFBIG, // File too large
|
||||
ENOSPC, // No space left on device
|
||||
ESPIPE, // Illegal seek
|
||||
EROFS, // Read-only file system
|
||||
EMLINK, // Too many links
|
||||
EPIPE, // Broken pipe
|
||||
EDQUOT, // Disk quota exceeded
|
||||
EDOM, // Function arg domain error
|
||||
ERANGE, // Out of range
|
||||
// TODO: more
|
||||
EILSEQ = 42,// Invalid byte seqence
|
||||
};
|
||||
|
||||
extern int errno;
|
||||
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef _FCNTL_H
|
||||
#define _FCNTL_H
|
||||
|
||||
/* Standard file decriptors */
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
/* File access modes */
|
||||
#define O_CREAT 0x0001 // Create if does not exist
|
||||
#define O_RDONLY 0x0002 // Read only
|
||||
#define O_WRONLY 0x0004 // Write only
|
||||
#define O_RDWR 0x0008 // Read and write
|
||||
#define O_APPEND 0x0010 // Always writes at the end (appends)
|
||||
#define O_TRUNC 0x0020 // Truncate file size and position to 0 on Open
|
||||
#define O_EXCL 0x0040 // Error if file exists (with O_CREAT)
|
||||
#define O_BIN 0x0080 // Read bytes, not text
|
||||
#define O_DIRECTORY 0x0100 // Error if file is not a directory
|
||||
// TODO: more!
|
||||
|
||||
/* TODO: File lock */
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef _FLOAT_H
|
||||
#define _FLOAT_H
|
||||
|
||||
#define FLT_DIG 6 // Float precision: 6 decimal digits
|
||||
#define DBL_DIG 15 // Double precision: 15 decimal digits
|
||||
#define LDBL_DIG 18 // Long double precision: 18 decimal digits
|
||||
|
||||
#define FLT_MAX 3.40282347e+38F // Maximum float value
|
||||
#define DBL_MAX 1.7976931348623157e+308 // Maximum double value
|
||||
#define LDBL_MAX 1.189731495357231765e+4932L // Max long double
|
||||
|
||||
#define FLT_MIN 1.17549435e-38F // Minimum positive normalized float
|
||||
#define DBL_MIN 2.2250738585072014e-308 // Min positive double
|
||||
#define LDBL_MIN 3.36210314311209350626e-4932L // Min positive long double
|
||||
|
||||
#define FLT_EPSILON 1.19209290e-7F // Smallest float increment
|
||||
#define DBL_EPSILON 2.2204460492503131e-16 // Smallest double increment
|
||||
#define LDBL_EPSILON 1.08420217248550443401e-19L // Smallest long double increment
|
||||
|
||||
#define FLT_MAX_EXP 128 // Max exponent for float
|
||||
#define DBL_MAX_EXP 1024 // Max exponent for double
|
||||
#define LDBL_MAX_EXP 16384 // Max exponent for long double
|
||||
|
||||
#define FLT_MIN_EXP -125 // Min exponent for float
|
||||
#define DBL_MIN_EXP -1021 // Min exponent for double
|
||||
#define LDBL_MIN_EXP -16381 // Min exponent for long double
|
||||
|
||||
#define FLT_RADIX 2 // Floating-point base (usually 2)
|
||||
#define FLT_MANT_DIG 24 // Number of digits in float mantissa
|
||||
#define DBL_MANT_DIG 53 // Number of digits in double mantissa
|
||||
#define LDBL_MANT_DIG 64 // Number of digits in long double mantissa
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef _LIMITS_H
|
||||
#define _LIMITS_H
|
||||
|
||||
// Chars are spectial :)
|
||||
#define CHAR_BIT 8
|
||||
#define CHAR_MIN 0
|
||||
|
||||
// Signed min
|
||||
#define SCHAR_MIN -127
|
||||
#define SHRT_MIN -32768
|
||||
#define INT_MIN -2147483648
|
||||
#define LONG_MIN -2147483648L
|
||||
#define LLONG_MIN -9223372036854775808LL
|
||||
|
||||
// Signed max
|
||||
#define SCHAR_MAX 127
|
||||
#define SHRT_MAX 32767
|
||||
#define INT_MAX 2147483647
|
||||
#define LONG_MAX 2147483647L
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
|
||||
// Unsigned max
|
||||
#define CHAR_MAX 255
|
||||
#define USHRT_MAX 65535
|
||||
#define UINT_MAX 4294967295U
|
||||
#define ULONG_MAX 4294967295UL
|
||||
#define ULLONG_MAX 18446744073709551615ULL
|
||||
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
#ifndef _MATH_H
|
||||
#define _MATH_H
|
||||
|
||||
// Constants
|
||||
#define M_E 2.71828182845904523536 // e
|
||||
#define M_LOG2E 1.44269504088896340736 // log_2 e
|
||||
#define M_LOG10E 0.43429448190325182765 // log_10 e
|
||||
#define M_LN2 0.69314718055994530941 // ln(2)
|
||||
#define M_LN10 2.30258509299404568402 // ln(10)
|
||||
#define M_PI 3.14159265358979323846 // pi
|
||||
#define M_PI_2 1.57079632679489661923 // pi/2
|
||||
#define M_PI_4 0.78539816339744830961 // pi/4
|
||||
#define M_1_PI 0.31830988618379067153 // 1/pi
|
||||
#define M_2_PI 0.63661977236758134307 // 2/pi
|
||||
#define M_SQRT2 1.41421356237309504880 // sqrt(2)
|
||||
#define M_SQRT1_2 0.70710678118654752440 // 1/sqrt(2)
|
||||
|
||||
// TODO:
|
||||
#define NAN (__builtin_inff())
|
||||
#define INFINITY (__builtin_nanf(""))
|
||||
|
||||
// Absolute value
|
||||
int abs(int n);
|
||||
double fabs(double n);
|
||||
|
||||
// Exponential & logarithmic
|
||||
double exp(double x);
|
||||
double exp2(double x);
|
||||
double log(double x);
|
||||
double log2(double x);
|
||||
double log10(double x);
|
||||
double logn(double x, double n);
|
||||
|
||||
// Power
|
||||
double sqrt(double x);
|
||||
double cbrt(double x);
|
||||
double hypot(double x, double y);
|
||||
double pow(double base, double expn);
|
||||
|
||||
// Trigonometric
|
||||
double sin(double x);
|
||||
double cos(double x);
|
||||
double tan(double x);
|
||||
double asin(double x);
|
||||
double acos(double x);
|
||||
double atan(double x);
|
||||
double atan2(double y, double x);
|
||||
|
||||
// Hyperbolic
|
||||
double sinh(double x);
|
||||
double cosh(double x);
|
||||
double tanh(double x);
|
||||
|
||||
// Rounding & remainder
|
||||
double floor(double x);
|
||||
double ceil(double x);
|
||||
double round(double x);
|
||||
double trunc(double x);
|
||||
double fmod(double x, double y);
|
||||
double modf(double x, double* iptr);
|
||||
|
||||
// Error handling
|
||||
double nan(const char* tagp);
|
||||
double inf();
|
||||
int isfinite(double x);
|
||||
int isinf(double x);
|
||||
int isnan(double x);
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef _SETJMP_H
|
||||
#define _SETJMP_H
|
||||
|
||||
typedef struct {
|
||||
void* _bp; // Base pointer
|
||||
void* _sp; // Stack pointer
|
||||
void* _pc; // Program counter
|
||||
} jmp_buf;
|
||||
|
||||
int setjmp(jmp_buf env);
|
||||
void longjmp(jmp_buf env, int value);
|
||||
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef char* va_list;
|
||||
#define va_start(ap, paramn) (void)((ap) = (char*)(&(paramn) + 1))
|
||||
#define va_end(ap) (void)((ap) = 0)
|
||||
#define va_arg(ap, type) (((type*)((ap) = ((ap) + sizeof(type))))[-1])
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef _BOOL_H
|
||||
#define _BOOL_H
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned int size_t;
|
||||
typedef signed int ssize_t;
|
||||
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Signed ints
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
// Unsigned ints
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// End Of File
|
||||
#define EOF (-1)
|
||||
|
||||
// File related macros
|
||||
#define BUFSIZ 512
|
||||
#define FILENAME_MAX 255
|
||||
#define FOPEN_MAX 32
|
||||
|
||||
// Seek positions
|
||||
#define SEEK_CUR 0
|
||||
#define SEEK_END 1
|
||||
#define SEEK_SET 2
|
||||
|
||||
/* The FILE struct */
|
||||
typedef struct _iobuf { // 24B
|
||||
unsigned char* _ptr; // File buffer base
|
||||
unsigned int _size; // Size of buffer
|
||||
int _offset; // Offset into file
|
||||
unsigned short _flag; // Open flags
|
||||
int _file; // File descriptor
|
||||
|
||||
char __reserved[6];
|
||||
} FILE;
|
||||
|
||||
// Standard file pointers
|
||||
extern FILE* stdin;
|
||||
extern FILE* stdout;
|
||||
extern FILE* stderr;
|
||||
|
||||
/* File operations */
|
||||
FILE* fopen(const char* path, const char* mode);
|
||||
int fclose(FILE* stream);
|
||||
size_t fread(void* ptr, size_t size, size_t count, FILE* stream);
|
||||
size_t fwrite(void* ptr, size_t size, size_t count, FILE* stream);
|
||||
int fseek(FILE* stream, long offset, int whence);
|
||||
long ftell(FILE* stream);
|
||||
void rewind(FILE* stream);
|
||||
int fflush(FILE* stream);
|
||||
|
||||
/* Character I/O */
|
||||
int getchar(void);
|
||||
int putchar(int c);
|
||||
int getc(FILE* stream);
|
||||
int putc(int c, FILE* stream);
|
||||
int ungetc(int c, FILE* stream);
|
||||
|
||||
/* Line I/O */
|
||||
char* fgets(char* str, int n, FILE* stream);
|
||||
int fputs(const char* str, FILE* stream);
|
||||
char* gets(char* str, int n);
|
||||
int puts(const char* str);
|
||||
|
||||
/* TODO: Error handling
|
||||
void perror(const char* s);
|
||||
int feof(FILE* stream);
|
||||
int ferror(FILE* stream);
|
||||
void clearerr(FILE* stream);
|
||||
*/
|
||||
|
||||
/* Formatted I/O */
|
||||
int printf(const char* fmt, ...);
|
||||
int vprintf(const char* fmt, va_list va);
|
||||
int fprintf(FILE* stream, const char* fmt, ...);
|
||||
int vfprintf(FILE* stream, const char* fmt, va_list va);
|
||||
// NOTE: (v)sprinf() Has been depricated and removed as it is unsafe (potencial buffer overflow). Please use (v)snprintf()
|
||||
int snprintf(char* str, size_t size, const char* fmt, ...);
|
||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va);
|
||||
int pprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, ...);
|
||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va);
|
||||
|
||||
int scanf(const char* fmt, ...);
|
||||
int vscanf(const char* fmt, va_list va);
|
||||
int fscanf(FILE* stream, const char* fmt, ...);
|
||||
int vfscanf(FILE* stream, const char* fmt, va_list va);
|
||||
int sscanf(const char* str, const char* fmt, ...);
|
||||
int vsscanf(const char* str, const char* fmt, va_list va);
|
||||
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
#define RAND_MAX 0x7FFFFFF
|
||||
|
||||
/* Memory allocation */
|
||||
void* malloc(size_t size);
|
||||
void* calloc(size_t count, size_t size);
|
||||
void* realloc(void* ptr, size_t size);
|
||||
void free(void* ptr);
|
||||
|
||||
/* Process controll */
|
||||
void _Exit(int status);
|
||||
void exit(int status);
|
||||
|
||||
// TODO: move atoi() here
|
||||
|
||||
/* Random number generator */
|
||||
int rand(void);
|
||||
void srand(unsigned int seed);
|
||||
|
||||
/* Sort & search */
|
||||
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
||||
void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void* memcpy(void* src, void* dst, size_t length);
|
||||
void* memcpy32(void* src, void* dst, size_t length);
|
||||
void* memset(void* dst, uint8_t value, size_t length);
|
||||
void* memset32(void* dst, uint32_t value, size_t length);
|
||||
|
||||
char* itoa(size_t val, int base);
|
||||
uint32_t atoi(const char* str);
|
||||
|
||||
char* strcpy(char* str1, const char* str2);
|
||||
char* strncpy(char* str1, const char* str2, size_t n);
|
||||
|
||||
char* strcat(char* str1, const char* str2);
|
||||
char* strncat(char* str1, const char* str2, size_t n);
|
||||
|
||||
char* strchr(const char* str, char c);
|
||||
char* strrchr(const char* str, char c);
|
||||
|
||||
int strcmp(const char* str1, const char* str2);
|
||||
int strncmp(const char* str1, const char* str2, size_t n);
|
||||
|
||||
size_t strlen(const char* str);
|
||||
|
||||
#endif
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef _SYS_GFX_H
|
||||
#define _SYS_GFX_H
|
||||
|
||||
#define BLACK 0x00000000 // 0
|
||||
#define RED 0x00ff0000 // 1
|
||||
#define GREEN 0x0000ff00 // 2
|
||||
#define YELLOW 0x00ffff00 // 3
|
||||
#define BLUE 0x000000ff // 4
|
||||
#define MAGENTA 0x00ff00ff // 5
|
||||
#define CYAN 0x0000ffff // 6
|
||||
#define WHITE 0x00ffffff // 7
|
||||
|
||||
uint32_t codeToColor(uint8_t code);
|
||||
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
#ifndef SOUND_NOTES_H
|
||||
#define SOUND_NOTES_H
|
||||
|
||||
/*
|
||||
|
||||
0 1 2 3 4 5 6 7 8
|
||||
C 16.35 32.7 65.41 130.81 261.63 523.25 1046.5 2093 4186
|
||||
C# 17.32 34.65 69.3 138.59 277.18 554.37 1108.73 2217.46 4434.92
|
||||
D 18.35 36.71 73.42 146.83 293.66 587.33 1174.66 2349.32 4698.63
|
||||
D# 19.45 38.89 77.78 155.56 311.13 622.25 1244.51 2489 4978
|
||||
E 20.6 41.2 82.41 164.81 329.63 659.25 1318.51 2637 5274
|
||||
F 21.83 43.65 87.31 174.61 349.23 698.46 1396.91 2793.83 5587.65
|
||||
F# 23.12 46.25 92.5 185 369.99 739.99 1479.98 2959.96 5919.91
|
||||
G 24.5 49 98 196 392 783.99 1567.98 3135.96 6271.93
|
||||
G# 25.96 51.91 103.83 207.65 415.3 830.61 1661.22 3322.44 6644.88
|
||||
A 27.5 55 110 220 440 880 1760 3520 7040
|
||||
A# 29.14 58.27 116.54 233.08 466.16 932.33 1864.66 3729.31 7458.62
|
||||
B 30.87 61.74 123.47 246.94 493.88 987.77 1975.53 3951 7902.13
|
||||
*/
|
||||
|
||||
// Note frequencies in Hz (rounded down)
|
||||
// b - Flat
|
||||
// s - Sharp (#)
|
||||
typedef enum {
|
||||
// 2nd Octave
|
||||
C2 = 65,
|
||||
Cs2 = 69,
|
||||
Db2 = Cs2,
|
||||
D2 = 73,
|
||||
Ds2 = 77,
|
||||
Eb2 = Ds2,
|
||||
E2 = 82,
|
||||
F2 = 87,
|
||||
Fs2 = 92,
|
||||
Gb2 = Fs2,
|
||||
G2 = 98,
|
||||
Gs2 = 103,
|
||||
Ab2 = Gs2,
|
||||
A2 = 110,
|
||||
As2 = 116,
|
||||
Hb2 = As2,
|
||||
H2 = 123,
|
||||
// 3rd Octave
|
||||
C3 = 130,
|
||||
Cs3 = 138,
|
||||
Db3 = Cs3,
|
||||
D3 = 146,
|
||||
Ds3 = 155,
|
||||
Eb3 = Ds3,
|
||||
E3 = 164,
|
||||
F3 = 174,
|
||||
Fs3 = 185,
|
||||
Gb3 = Fs3,
|
||||
G3 = 196,
|
||||
Gs3 = 207,
|
||||
Ab3 = Gs3,
|
||||
A3 = 220,
|
||||
As3 = 233,
|
||||
Hb3 = As3,
|
||||
H3 = 246,
|
||||
// 4th Octave
|
||||
C4 = 261,
|
||||
Cs4 = 277,
|
||||
Db4 = Cs4,
|
||||
D4 = 293,
|
||||
Ds4 = 311,
|
||||
Eb4 = Ds4,
|
||||
E4 = 329,
|
||||
F4 = 349,
|
||||
Fs4 = 370,
|
||||
Gb4 = Fs4,
|
||||
G4 = 392,
|
||||
Gs4 = 415,
|
||||
Ab4 = Gs4,
|
||||
A4 = 440, // Standard A, 440Hz
|
||||
As4 = 466,
|
||||
Hb4 = As4,
|
||||
H4 = 493,
|
||||
// 5th Octave
|
||||
C5 = 523,
|
||||
Cs5 = 554,
|
||||
Db5 = Cs5,
|
||||
D5 = 587,
|
||||
Ds5 = 622,
|
||||
Eb5 = Ds5,
|
||||
E5 = 659,
|
||||
F5 = 698,
|
||||
Fs5 = 739,
|
||||
Gb5 = Fs5,
|
||||
G5 = 783,
|
||||
Gs5 = 830,
|
||||
Ab5 = Gs5,
|
||||
A5 = 880,
|
||||
As5 = 932,
|
||||
Hb5 = As5,
|
||||
H5 = 987,
|
||||
} note_t;
|
||||
|
||||
typedef enum {
|
||||
WHOLE = 1,
|
||||
HALF = 2,
|
||||
QUARTER = 4,
|
||||
EIGHT = 8,
|
||||
SIXTEENTH = 16,
|
||||
THIRTYSECONDTH = 32,
|
||||
} beatType_t;
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef _SYSCALL_H
|
||||
#define _SYSCALL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SYSCALL_COUNT 9
|
||||
|
||||
typedef enum {
|
||||
SYS_EXIT,
|
||||
SYS_READ,
|
||||
SYS_WRITE,
|
||||
SYS_OPEN,
|
||||
SYS_CLOSE,
|
||||
SYS_SEEK,
|
||||
SYS_MALLOC,
|
||||
SYS_FREE,
|
||||
SYS_SLEEP,
|
||||
} SYSCALL_NUMBERS;
|
||||
|
||||
inline int syscall(int nr, int a0, int a1, int a2, int a3, int a4) {
|
||||
int ret;
|
||||
__asm__ volatile (
|
||||
"movl %1, %%eax\n" // Syscall number
|
||||
"movl %2, %%ebx\n" // Arg 0
|
||||
"movl %3, %%ecx\n" // Arg 1
|
||||
"movl %4, %%edx\n" // Arg 2
|
||||
"movl %5, %%esi\n" // Arg 3
|
||||
"movl %6, %%edi\n" // Arg 4
|
||||
"int $0x80\n" // Trigger syscall
|
||||
"movl %%eax, %0" // Return
|
||||
: "=r"(ret) // Output
|
||||
: "r"(nr), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4) // Input
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Syscall wrappers */
|
||||
static inline int _exit(int status) { return syscall(SYS_EXIT, status, 0, 0, 0, 0); }
|
||||
static inline int read(int fd, void* ptr, size_t count) { return syscall(SYS_READ, fd, (int)ptr, (int)count, 0, 0); }
|
||||
static inline int write(int fd, const void* ptr, size_t count) { return syscall(SYS_WRITE, fd, (int)ptr, (int)count, 0, 0); }
|
||||
static inline int open(const char* path, int oflag) { return syscall(SYS_OPEN, (int)path, oflag, 0, 0, 0); }
|
||||
static inline int close(int fd) { return syscall(SYS_CLOSE, fd, 0, 0, 0, 0); }
|
||||
static inline int seek(int fd, size_t offset, int whence) { return syscall(SYS_SEEK, fd, offset, whence, 0, 0); }
|
||||
static inline int _malloc(int size) { return syscall(SYS_MALLOC, size, 0, 0, 0, 0); }
|
||||
static inline int _free(void* ptr) { return syscall(SYS_FREE, (int)ptr, 0, 0, 0, 0); }
|
||||
static inline int _sleep(int t) { return syscall(SYS_SLEEP, t, 0, 0, 0, 0); }
|
||||
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void sleep(size_t s);
|
||||
void msleep(size_t ms);
|
||||
void usleep(size_t us);
|
||||
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
include ../defaults.mk
|
||||
|
||||
INC = ./include
|
||||
BIN = ./bin
|
||||
|
||||
SRCS = $(shell find . -name '*.c')
|
||||
OBJS = $(patsubst %.c, $(BIN)/%.o, $(SRCS))
|
||||
OUT = ./libc.o
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OUT)
|
||||
$(OUT): $(OBJS)
|
||||
$(AR) $(ARFLAGS) rcs $@ $^
|
||||
|
||||
$(BIN)/%.o: %.c
|
||||
@mkdir -p $(BIN)/$(dir $<)
|
||||
$(CC) $(CFLAGS) -I$(INC) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -fr $(BIN) $(OUT)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
int abs(int n) {
|
||||
return (n < 0) ? -n : n;
|
||||
}
|
||||
|
||||
double fabs(double x) {
|
||||
return (x < 0.0) ? -x : x;
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
double nan(const char* tagp) {
|
||||
(void)tagp;
|
||||
|
||||
// Create a NaN bit pattern in IEEE 754
|
||||
uint64_t nanBits = 0x7ff8000000000000ULL;
|
||||
double result;
|
||||
memcpy(&result, &nanBits, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double inf() {
|
||||
// Create an infinity bit pattern in IEEE 754
|
||||
uint64_t infBits = 0x7ff0000000000000ULL;
|
||||
double result;
|
||||
memcpy(&result, &infBits, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
int isfinite(double x) {
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &x, sizeof(bits));
|
||||
uint64_t exponent = (bits >> 52) & 0x7ff;
|
||||
return exponent != 0x7ff;
|
||||
}
|
||||
|
||||
int isinf(double x) {
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &x, sizeof(bits));
|
||||
uint64_t exponent = (bits >> 52) & 0x7ff;
|
||||
uint64_t mantissa = bits & 0xfffffffffffff;
|
||||
return (exponent == 0x7ff && mantissa == 0);
|
||||
}
|
||||
|
||||
int isnan(double x) {
|
||||
uint64_t bits;
|
||||
memcpy(&bits, &x, sizeof(bits));
|
||||
uint64_t exponent = (bits >> 52) & 0x7ff;
|
||||
uint64_t mantissa = bits & 0xfffffffffffff;
|
||||
return (exponent == 0x7ff && mantissa != 0);
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#define _EXP_TAYLOR_TERMS 10
|
||||
#define _EXP2_TAYLOR_TERMS 5
|
||||
|
||||
double exp(double x) {
|
||||
if (x == 0.0) return 1.0;
|
||||
if (x < 0.0) return 1.0 / exp(-x);
|
||||
|
||||
double sum = 1.0; // Result
|
||||
double term = 1.0; // Curent term in the series
|
||||
|
||||
/*
|
||||
Calculate the Taylor series:
|
||||
e^x = 1 + x + x^2/2! + x^3/3! + ...
|
||||
*/
|
||||
for (int i = 1; i < _EXP_TAYLOR_TERMS; i++) {
|
||||
term *= x / (double)i;
|
||||
sum += term;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
double exp2(double x) {
|
||||
if (x == 0.0) return 1.0;
|
||||
if (x < 0.0) return 1.0 / exp2(-x);
|
||||
|
||||
int n = (int)x; // Integer part
|
||||
double frac = x - n;// Fractional part
|
||||
|
||||
// Integer power of 2
|
||||
double result = (double)(1 << n); // 2^n is just 1 << n
|
||||
|
||||
// Approximate the fractional part
|
||||
double sum = 1.0;
|
||||
double term = frac;
|
||||
|
||||
for (int i = 1; i < _EXP2_TAYLOR_TERMS; i++) {
|
||||
sum += term;
|
||||
term *= frac / (i+1);
|
||||
}
|
||||
|
||||
return result * sum;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
double sinh(double x) {
|
||||
return (exp(x) - exp(-x)) / 2.0;
|
||||
}
|
||||
|
||||
double cosh(double x) {
|
||||
return (exp(x) + exp(-x)) / 2.0;
|
||||
}
|
||||
|
||||
double tanh(double x) {
|
||||
double ex = exp(x);
|
||||
double emx = exp(-x);
|
||||
return (ex - emx) / (ex + emx);
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#define _LOG_TERMS 20
|
||||
|
||||
double log(double x) {
|
||||
if (x <= 0.0) return -INFINITY;
|
||||
|
||||
double result = 0.0;
|
||||
double term = (x - 1.0) / (x + 1.0);
|
||||
double termSquared = term*term;
|
||||
double numerator = term;
|
||||
|
||||
for (int i = 1; i < _LOG_TERMS; i++) {
|
||||
result += numerator / (double)i;
|
||||
numerator *= termSquared;
|
||||
}
|
||||
|
||||
return 2.0 * result;
|
||||
}
|
||||
|
||||
double log2(double x) {
|
||||
if (x <= 0.0) return -INFINITY;
|
||||
return log(x) / M_LN2;
|
||||
}
|
||||
|
||||
double log10(double x) {
|
||||
if (x <= 0.0) return -INFINITY;
|
||||
return log(x) / M_LN10;
|
||||
}
|
||||
|
||||
double logn(double x, double n) {
|
||||
if (x <= 0.0) return -INFINITY;
|
||||
return log(x) / log(n);
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#define _POW_LOOP_MAX 60
|
||||
|
||||
double sqrt(double x) {
|
||||
if (x < 0.0) return -NAN;
|
||||
|
||||
double result = x;
|
||||
double oldResult = 0.0;
|
||||
|
||||
while (result != oldResult) {
|
||||
oldResult = result;
|
||||
result = 0.5 * (result + x/result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double cbrt(double x) {
|
||||
double result = x;
|
||||
double oldResult = 0.0;
|
||||
|
||||
while (result != oldResult) {
|
||||
oldResult = result;
|
||||
result = (2.0 * result + x/(result * result)) / 3.0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double hypot(double x, double y) {
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
double pow(double base, double expn) { // exp is a function so we have to use expn
|
||||
if (base == 0.0 && expn == 0.0) return NAN;
|
||||
if (base == 0.0) return 0.0;
|
||||
if (expn == 0.0) return 1.0;
|
||||
|
||||
return exp(expn * log(base));
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
double round(double x) {
|
||||
double res;
|
||||
__asm__ volatile (
|
||||
"fldl %1\n" // Load x to the FPU stack
|
||||
"frndint\n" // Round to nearest integer
|
||||
"fstpl %0" // Store result
|
||||
: "=m"(res)
|
||||
: "m"(x)
|
||||
);
|
||||
if ((x - res) == 0.5 || (x - res) == -0.5) {
|
||||
// Halfway cases: round away from zero
|
||||
res += (x > 0) ? 1.0 : -1.0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
double floor(double x) {
|
||||
double res = round(x);
|
||||
if (res > x) { res -= 1.0; }
|
||||
return res;
|
||||
}
|
||||
|
||||
double ceil(double x){
|
||||
double res = round(x);
|
||||
if (res < x) { res += 1.0; }
|
||||
return res;
|
||||
}
|
||||
|
||||
double trunc(double x) {
|
||||
double res = round(x);
|
||||
if (x < 0 && x != res) { res -= 1.0; }
|
||||
return res;
|
||||
}
|
||||
|
||||
double fmod(double x, double y) {
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
double modf(double x, double* iptr) {
|
||||
double whole = trunc(x);
|
||||
*iptr = whole;
|
||||
return x - whole;
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
double sin(double x) {
|
||||
double res;
|
||||
__asm__ volatile (
|
||||
"fldl %1\n" // Load x to the FPU stack
|
||||
"fsin\n" // Compute sin(x)
|
||||
"fstpl %0" // Store result
|
||||
: "=m"(res) : "m"(x)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
double cos(double x) {
|
||||
double res;
|
||||
__asm__ volatile (
|
||||
"fldl %1\n" // Load x to the FPU stack
|
||||
"fcos\n" // Compute cos(x)
|
||||
"fstpl %0" // Store result
|
||||
: "=m"(res) : "m"(x)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
double tan(double x) {
|
||||
return sin(x) / cos(x);
|
||||
}
|
||||
|
||||
double asin(double x) {
|
||||
return atan2(x, sqrt(1 - x*x));
|
||||
}
|
||||
|
||||
double acos(double x) {
|
||||
return M_PI_2 - asin(x);
|
||||
}
|
||||
|
||||
double atan(double x) {
|
||||
double res;
|
||||
__asm__ volatile (
|
||||
"fld1\n" // Load 1.0 to the FPU stack
|
||||
"fldl %1\n" // Load x to the FPU stack
|
||||
"fpatan\n" // Compute atan(x)
|
||||
"fstpl %0" // Store result
|
||||
: "=m"(res) : "m"(x)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
double atan2(double y, double x) {
|
||||
double res;
|
||||
__asm__ volatile (
|
||||
"fldl %2\n" // Load x to the FPU stack
|
||||
"fldl %1\n" // Load y to the FPU stack
|
||||
"fpatan\n" // Compute atan2(y, x)
|
||||
"fstpl %0" // Store the result
|
||||
: "=m"(res) : "m"(y), "m"(x)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <setjmp.h>
|
||||
|
||||
int setjmp(jmp_buf env) {
|
||||
__asm__ volatile (
|
||||
"mov %%ebp, %0\n" // Save BP
|
||||
"mov %%esp, %1\n" // Save SP
|
||||
"call 1f\n" // Call label to push PC to the stack
|
||||
"1:\n" // Label
|
||||
"pop %2\n" // Save PC
|
||||
: "=m"(env._bp), "=m"(env._sp), "=m"(env._pc) // Locations
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void longjmp(jmp_buf env, int value) {
|
||||
if (value == 0) return;
|
||||
|
||||
__asm__ volatile (
|
||||
"mov %0, %%ebp\n" // Restore BP
|
||||
"mov %1, %%esp\n" // Restore SP
|
||||
"mov %2, %%eax\n" // Put return address into A
|
||||
"jmp *%%eax\n" // Jump to A
|
||||
:: "m"(env._bp), "m"(env._sp), "m"(env._pc)
|
||||
);
|
||||
// This point is unreachable :)
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int getchar(void) { return getc(stdin); }
|
||||
int putchar(int c) { return putc(c, stdout); }
|
||||
|
||||
int getc(FILE* stream) {
|
||||
if (!stream) { return EOF; }
|
||||
|
||||
unsigned char ch = '\0';
|
||||
ssize_t res = read(stream->_file, &ch, 1);
|
||||
if (res <= 0) { return EOF; }
|
||||
|
||||
return (int)ch;
|
||||
}
|
||||
|
||||
int putc(int c, FILE* stream) {
|
||||
if (!stream) { return EOF; }
|
||||
|
||||
unsigned char ch = (unsigned char)c;
|
||||
ssize_t res = write(stream->_file, &c, 1);
|
||||
if (res <= 0) { return EOF; }
|
||||
|
||||
return (int)ch;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
int ungetc(int c, FILE* stream) { return EOF; }
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
FILE* stdin;
|
||||
FILE* stdout;
|
||||
FILE* stderr;
|
||||
|
||||
FILE* fopen(const char* path, const char* mode) {
|
||||
FILE* fp = (FILE*)malloc(sizeof(FILE));
|
||||
if (!fp) { return NULL; }
|
||||
|
||||
int flags = 0;
|
||||
if (strcmp(mode, "r") == 0) { flags = O_RDONLY; }
|
||||
else if (strcmp(mode, "w") == 0) { flags = O_WRONLY | O_CREAT | O_TRUNC; }
|
||||
else if (strcmp(mode, "a") == 0) { flags = O_WRONLY | O_CREAT | O_APPEND; }
|
||||
else if (strcmp(mode, "r+") == 0) { flags = O_RDWR; }
|
||||
else if (strcmp(mode, "w+") == 0) { flags = O_RDWR | O_CREAT | O_TRUNC; }
|
||||
else if (strcmp(mode, "a+") == 0) { flags = O_RDWR | O_CREAT | O_APPEND; }
|
||||
else { // Unsuppored mode
|
||||
free(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd = open(path, flags);
|
||||
if (fd == -1) {
|
||||
free(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp->_file = fd;
|
||||
fp->_ptr = NULL;
|
||||
fp->_size = 0;
|
||||
fp->_offset = 0;
|
||||
fp->_flag = flags;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
int fclose(FILE* stream) {
|
||||
if (!stream) { return -1; }
|
||||
int ret = close(stream->_file);
|
||||
free(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t fread(void* ptr, size_t size, size_t count, FILE* stream) {
|
||||
if (!stream || !ptr || size == 0 || count == 0) { return 0; }
|
||||
|
||||
size_t total = size * count;
|
||||
ssize_t readb = read(stream->_file, ptr, total);
|
||||
|
||||
if (readb < 0) return 0;
|
||||
|
||||
stream->_offset += readb;
|
||||
return readb / size;
|
||||
}
|
||||
|
||||
size_t fwrite(void* ptr, size_t size, size_t count, FILE* stream) {
|
||||
if (!stream || !ptr || size == 0 || count == 0) { return 0; }
|
||||
|
||||
size_t total = size * count;
|
||||
ssize_t writtenb = write(stream->_file, ptr, total);
|
||||
|
||||
if (writtenb < 0) return 0;
|
||||
|
||||
stream->_offset += writtenb;
|
||||
return writtenb / size;
|
||||
}
|
||||
|
||||
// TODO
|
||||
int fseek(FILE* stream, long offset, int whence);
|
||||
long ftell(FILE* stream);
|
||||
void rewind(FILE* stream);
|
||||
int fflush(FILE* stream);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
char* fgets(char* str, int n, FILE* stream) {
|
||||
if (!str || !stream || n <= 1) { return NULL; }
|
||||
|
||||
char* dest = str;
|
||||
int ch;
|
||||
|
||||
while (--n > 0 && (ch = getc(stream)) != EOF) {
|
||||
*dest++ = ch;
|
||||
if (ch == '\n') break; // Stop at newline
|
||||
}
|
||||
|
||||
*dest = '\0'; // Null terminate
|
||||
|
||||
return (dest == str) ? NULL : str;
|
||||
}
|
||||
|
||||
int fputs(const char* str, FILE* stream) {
|
||||
if (!str || !stream) { return EOF; }
|
||||
|
||||
while (*str) {
|
||||
if (putc(*str++, stream) == EOF) { return EOF; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline char* gets(char* str, int n) { return fgets(str, n, stdin); }
|
||||
inline int puts(const char* str) { return fputs(str, stdout); }
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Internal definitions */
|
||||
typedef struct {
|
||||
int buflen;
|
||||
int offset;
|
||||
char* buf;
|
||||
} printfEnv_t;
|
||||
|
||||
/* Helpers */
|
||||
// Digit to character
|
||||
static char _dtoc(int digit) { return digit < 10 ? '0' + digit : 'a' + (digit - 10); }
|
||||
static double _fabs(double x) { return (x < 0.0) ? -x : x; }
|
||||
static void _fmtInt(void (*outfn)(char c, void* arg), void* arg, int n, int base, int width, char padc) {
|
||||
char buf[32];
|
||||
int negative = 0;
|
||||
int i = 0;
|
||||
|
||||
if (n < 0 && base == 10) {
|
||||
negative = 1;
|
||||
n = -n;
|
||||
}
|
||||
|
||||
// Convert number, this will be done in reverse
|
||||
do {
|
||||
buf[i++] = _dtoc(n % base);
|
||||
n /= base;
|
||||
} while (n > 0);
|
||||
|
||||
// Padding
|
||||
while (i < width) { buf[i++] = padc; }
|
||||
// Add negative sign
|
||||
if (negative) { buf[i++] = '-'; }
|
||||
|
||||
// Funny arrow
|
||||
while (i --> 0) { outfn(buf[i], arg); }
|
||||
}
|
||||
|
||||
static void _fmtFloat(void (*outfn)(char c, void* arg), void* arg, double f) {
|
||||
int whole = (int)f;
|
||||
double frac = _fabs(f - whole);
|
||||
int decPlaces = 6;
|
||||
|
||||
// Add negative sign
|
||||
if (f < 0) { outfn('-', arg); }
|
||||
|
||||
// Print whole part
|
||||
_fmtInt(outfn, arg, whole, 10, 0, ' ');
|
||||
|
||||
// Print decimal point
|
||||
outfn('.', arg);
|
||||
|
||||
// Format fractional part
|
||||
for (int i = 0; i < decPlaces; i++) {
|
||||
frac *= 10;
|
||||
int digit = (int)frac;
|
||||
outfn('0' + digit, arg);
|
||||
frac -= digit;
|
||||
}
|
||||
}
|
||||
|
||||
static void _dynamicPutc(char c, void* arg) {
|
||||
printfEnv_t* env = (printfEnv_t*)arg;
|
||||
if (!env->buf) { return; }
|
||||
|
||||
if (env->offset < env->buflen) {
|
||||
env->buf[env->offset++] = c;
|
||||
} else {
|
||||
env->buflen *= 2;
|
||||
env->buf = realloc(env->buf, env->buflen);
|
||||
|
||||
// If there's not enough memory, we chatch the NULL pointer in the fwrite() call
|
||||
if (!env->buf) { return; }
|
||||
|
||||
env->buf[env->offset++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static void _staticPutc(char c, void* arg) {
|
||||
printfEnv_t* env = (printfEnv_t*)arg;
|
||||
if (!env->buf) { return; }
|
||||
|
||||
if (env->offset < env->buflen) {
|
||||
env->buf[env->offset] = c;
|
||||
env->offset++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Impementation */
|
||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va) {
|
||||
int i = 0;
|
||||
|
||||
while (fmt[i] != '\0') {
|
||||
if (fmt[i] != '%') { // Just print the character
|
||||
outfn(fmt[i++], arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
i++; // Consume the %
|
||||
if (fmt[i] == '\0') { // End of string
|
||||
outfn('%', arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Parse fmt string
|
||||
int width = 0;
|
||||
char pad = ' ';
|
||||
|
||||
// Check for zero pad and parse width
|
||||
if (isdigit(fmt[i])) {
|
||||
if (fmt[i] == '0') { pad = '0'; i++; }
|
||||
|
||||
while (isdigit(fmt[i])) { // Parse width
|
||||
width *= 10;
|
||||
width += fmt[i++] - '0';
|
||||
}
|
||||
}
|
||||
|
||||
// Parse specifier
|
||||
switch (fmt[i]) {
|
||||
case 'c': { // Character
|
||||
char c = va_arg(va, char);
|
||||
outfn(c, arg);
|
||||
break;
|
||||
} case 's': { // String
|
||||
char* s = va_arg(va, char*);
|
||||
while (*s) { outfn(*s++, arg); }
|
||||
break;
|
||||
} case 'd': { // Decimal number
|
||||
int d = va_arg(va, int);
|
||||
_fmtInt(outfn, arg, d, 10, width, pad);
|
||||
break;
|
||||
} case 'x': { // Hex number
|
||||
int x = va_arg(va, int);
|
||||
_fmtInt(outfn, arg, x, 16, width, pad);
|
||||
break;
|
||||
} case 'f': { // Float
|
||||
double f = va_arg(va, double);
|
||||
_fmtFloat(outfn, arg, f);
|
||||
break;
|
||||
} default: {
|
||||
outfn(fmt[i], arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va) {
|
||||
printfEnv_t env;
|
||||
env.buflen = size;
|
||||
env.offset = 0;
|
||||
env.buf = str;
|
||||
|
||||
// Format the string
|
||||
int ret = vpprintf(_staticPutc, &env, fmt, va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfprintf(FILE* stream, const char* fmt, va_list va) {
|
||||
printfEnv_t env;
|
||||
env.buflen = 128;
|
||||
env.offset = 0;
|
||||
env.buf = malloc(env.buflen);
|
||||
if (!env.buf) { return -1; }
|
||||
|
||||
// Format the string
|
||||
int ret = vpprintf(_dynamicPutc, &env, fmt, va);
|
||||
|
||||
// Write to stream
|
||||
if (fwrite(env.buf, 1, ret, stream) != 1) { return -1; }
|
||||
|
||||
free(env.buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vprintf(const char* fmt, va_list va) { return vfprintf(stdout, fmt, va); }
|
||||
|
||||
// Print using an custom putc function
|
||||
int pprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vpprintf(outfn, arg, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to a buffer
|
||||
int snprintf(char* str, size_t size, const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vsnprintf(str, size, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to a stream
|
||||
int fprintf(FILE* stream, const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vfprintf(stream, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to stdout
|
||||
int printf(const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vfprintf(stdout, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
|
||||
void* malloc(size_t size) { return (void*)_malloc(size); }
|
||||
|
||||
void* calloc(size_t count, size_t size) {
|
||||
size_t total = count * size;
|
||||
void* ptr = malloc(total);
|
||||
|
||||
if (!ptr) { return NULL; }
|
||||
memset(ptr, 0, total);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* realloc(void* ptr, size_t size) {
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ptr == NULL) { return malloc(size); }
|
||||
|
||||
void* newptr = malloc(size);
|
||||
if (!newptr) { return NULL; }
|
||||
|
||||
// TODO: retrieve the old size
|
||||
memcpy(newptr, ptr, size);
|
||||
|
||||
free(ptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
void free(void* ptr) { _free(ptr); }
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
// Exits without cleaning up
|
||||
void _Exit(int status) { _exit(status); }
|
||||
|
||||
void exit(int status) {
|
||||
// TODO: Close open files
|
||||
// TODO: Free malloced buffers
|
||||
|
||||
_Exit(status);
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
// taken from glibc
|
||||
#define RAND_A 1103515245
|
||||
#define RAND_C 12345
|
||||
|
||||
static size_t _next = 1;
|
||||
|
||||
int rand(void) {
|
||||
_next = (RAND_A * _next + RAND_C) & RAND_MAX;
|
||||
return (int)(_next % (size_t)(RAND_MAX + 1));
|
||||
}
|
||||
|
||||
void srand(size_t seed) { _next = seed; }
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void* bsearch(const void* key, const void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) {
|
||||
size_t left = 0;
|
||||
size_t right = nitem;
|
||||
|
||||
while (left < right) {
|
||||
size_t mid = left + (right - left) / 2;
|
||||
void* midEl = (char*)base + mid * size;
|
||||
|
||||
int cmp = compar(key, midEl);
|
||||
|
||||
if (cmp < 0) {
|
||||
right = mid;
|
||||
} else if (cmp > 0) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
return midEl;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
void swap(void* a, void* b, size_t size) {
|
||||
char temp[size];
|
||||
memcpy(temp, a, size);
|
||||
memcpy(a, b, size);
|
||||
memcpy(b, temp, size);
|
||||
}
|
||||
|
||||
void* partition(void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) {
|
||||
char* pivot = (char*)base + (nitem - 1) * size;
|
||||
char* i = (char*)base;
|
||||
|
||||
for (char* j = (char*)base; j < pivot; j += size) {
|
||||
if (compar(j, pivot) < 0) {
|
||||
swap(i, j, size);
|
||||
i += size;
|
||||
}
|
||||
}
|
||||
|
||||
swap(i, pivot, size);
|
||||
return i;
|
||||
}
|
||||
|
||||
void qsort(void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) {
|
||||
if (nitem <= 1) { return; }
|
||||
|
||||
char* pivot = (char*)partition(base, nitem, size, compar);
|
||||
size_t lsize = (pivot - (char*)base) / size;
|
||||
size_t rsize = nitem - lsize - 1;
|
||||
|
||||
qsort(base, lsize, size, compar);
|
||||
qsort(pivot + size, rsize, size, compar);
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
unsigned int atoi(const char* str) {
|
||||
unsigned int res = 0;
|
||||
|
||||
// TODO: Add error checking
|
||||
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
res = res * 10 + (*str++ - '0');
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
// Source: http://www.strudel.org.uk/itoa/
|
||||
char* itoa(size_t val, int base) {
|
||||
static char buf[32] = { 0 };
|
||||
|
||||
if (base == 0 || base > 16) { return NULL; }
|
||||
|
||||
if (val == 0) {
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 30; val && i; i--, val /= base) {
|
||||
buf[i] = "0123456789abcdef"[val % base];
|
||||
}
|
||||
|
||||
return &buf[i + 1];
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void* memcpy(void* src, void* dst, uint32_t length) {
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
*((uint8_t*)dst + i) = *((uint8_t*)src + i);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
void* memcpy32(void* src, void* dst, uint32_t length) {
|
||||
for (uint32_t i = 0; i * 4 < length; i++) {
|
||||
*((uint32_t*)dst + i) = *((uint32_t*)src + i);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void* memset(void* dst, uint8_t value, size_t length) {
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
*(uint8_t*)(dst + i) = value;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
void* memset32(void* dst, uint32_t value, size_t length) {
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
*(uint32_t*)(dst + i) = value;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
char* strcat(char* str1, const char* str2) {
|
||||
char* s = str1;
|
||||
while (*s != '\0') { s++; }
|
||||
strcpy(s, str2);
|
||||
return str1;
|
||||
}
|
||||
|
||||
char* strncat(char* str1, const char* str2, size_t n) {
|
||||
char* s = str1;
|
||||
while (*s != '\0') { s++; }
|
||||
strncpy(s, str2, n);
|
||||
return str1;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
char* strchr(const char* str, char c) {
|
||||
const char* s = str;
|
||||
while (*s != '\0' && *s != c) { s++; }
|
||||
return (*s == c) ? (char*)s : NULL;
|
||||
}
|
||||
|
||||
char* strrchr(const char* str, char c) { return NULL; } // TODO
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
int strcmp(const char* str1, const char* str2) {
|
||||
while (*str1 != '\0' && *str1 == *str2) {
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
|
||||
uint8_t c1 = (*(uint8_t*)str1);
|
||||
uint8_t c2 = (*(uint8_t*)str2);
|
||||
|
||||
return ((c1 < c2) ? -1 : (c1 > c2));
|
||||
}
|
||||
|
||||
int strncmp(const char* str1, const char* str2, size_t n) {
|
||||
if (n == 0) { return 0; }
|
||||
while (n-- > 0 && *str1 == *str2) {
|
||||
if (n == 0 || *str1 == '\0') { return 0; }
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
|
||||
uint8_t c1 = (*(uint8_t*)str1);
|
||||
uint8_t c2 = (*(uint8_t*)str2);
|
||||
|
||||
return ((c1 < c2) ? -1 : (c1 > c2));
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
char* strcpy(char* str1, const char* str2) {
|
||||
char* dst = str1;
|
||||
const char* src = str2;
|
||||
while ((*dst++ = *src++) != '\0');
|
||||
return str1;
|
||||
}
|
||||
|
||||
char* strncpy(char* str1, const char* str2, size_t n) {
|
||||
char* dst = str1;
|
||||
const char* src = str2;
|
||||
while (n > 0) {
|
||||
n--;
|
||||
if ((*dst++ = *src++) == '\0') {
|
||||
memset(dst, '\0', n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return str1;
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
size_t strlen(const char* str) {
|
||||
const char* p = str;
|
||||
while (*++p != '\0');
|
||||
return (size_t)(p - str);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/gfx.h>
|
||||
|
||||
uint32_t codeToColor(uint8_t code) {
|
||||
switch (code) {
|
||||
case 0: return BLACK;
|
||||
case 1: return RED;
|
||||
case 2: return GREEN;
|
||||
case 3: return YELLOW;
|
||||
case 4: return BLUE;
|
||||
case 5: return MAGENTA;
|
||||
case 6: return CYAN;
|
||||
case 7: return WHITE;
|
||||
default: return BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <time.h>
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Seconds sleep
|
||||
void sleep(size_t s) { _sleep(s*1000); }
|
||||
|
||||
// Millisecond sleep
|
||||
void msleep(size_t ms) { _sleep(ms); }
|
||||
|
||||
// Microsecond sleep
|
||||
void usleep(size_t us) { /* TODO */ }
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
IMG = kern.img
|
||||
BOOT = ./boot
|
||||
KERNEL = ./kernel
|
||||
LIBC = ./libc
|
||||
|
||||
MODULES = $(BOOT)\
|
||||
$(KERNEL)\
|
||||
$(LIBC)
|
||||
MODULES = $(KERNEL)
|
||||
|
||||
.PHONY: all clean $(MODULES) qemu
|
||||
|
||||
all: $(IMG)
|
||||
$(IMG): $(MODULES)
|
||||
dd if=/dev/zero of=$(IMG) bs=512 count=131072
|
||||
dd if=$(BOOT)/stage1.bin of=$(IMG) bs=512 seek=0 conv=notrunc
|
||||
dd if=$(BOOT)/stage2.bin of=$(IMG) bs=512 seek=1 conv=notrunc
|
||||
echo ',,b,*' | sfdisk $(IMG) >/dev/null
|
||||
echo 'drive A:\n\tfile="$(IMG)"\n\tpartition=1' > ~/.mtoolsrc
|
||||
mformat -F 'A:'
|
||||
mcopy $(KERNEL)/kern.bin 'A:'
|
||||
|
||||
all: $(MODULES)
|
||||
$(MODULES):
|
||||
$(MAKE) -C $@
|
||||
|
||||
@@ -31,5 +17,5 @@ qemu:
|
||||
-drive format=raw,file=$(IMG),index=0,media=disk\
|
||||
-m 256M -accel tcg -monitor stdio -net none\
|
||||
-rtc base=localtime,clock=host,driftfix=slew\
|
||||
-audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0
|
||||
-audiodev pipewire,id=audio0 -machine pcspk-audiodev=audio0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user