Initial Commit

This commit is contained in:
kaguya
2026-04-14 22:52:24 -04:00
commit 426ad76676
184 changed files with 11033 additions and 0 deletions
+159
View File
@@ -0,0 +1,159 @@
#include "ata.h"
#include "io.h" // your existing inb/outb/insw
#include "stdio.h"
#include "memory.h"
#include <stdbool.h>
#define ATA_PRIMARY_DATA 0x1F0
#define ATA_PRIMARY_ERROR 0x1F1
#define ATA_PRIMARY_SECCOUNT 0x1F2
#define ATA_PRIMARY_LBALOW 0x1F3
#define ATA_PRIMARY_LBAMID 0x1F4
#define ATA_PRIMARY_LBAHIGH 0x1F5
#define ATA_PRIMARY_DRIVE 0x1F6
#define ATA_PRIMARY_STATUS 0x1F7
#define ATA_PRIMARY_COMMAND 0x1F7
#define ATA_STATUS_BSY 0x80
#define ATA_STATUS_DRDY 0x40
#define ATA_STATUS_DRQ 0x08
#define ATA_STATUS_ERR 0x01
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_CMD_READ_SECTORS 0x20
static void ata_wait_ready(void)
{
while (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_BSY) {}
while (!(x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_DRDY)) {}
}
static bool ata_poll(void)
{
// 400 ns delay
for (int i = 0; i < 4; i++)
x86_64_inb(ATA_PRIMARY_STATUS);
uint8_t status;
while ((status = x86_64_inb(ATA_PRIMARY_STATUS)) & ATA_STATUS_BSY);
if (status & ATA_STATUS_ERR) return false;
while (!(status & ATA_STATUS_DRQ)) {
status = x86_64_inb(ATA_PRIMARY_STATUS);
if (status & ATA_STATUS_ERR) return false;
}
return true;
}
void ata_init(void)
{
x86_64_outb(0x3F6, 0x02); // disable interrupts on primary controller
ata_wait_ready();
x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); // select master
ata_wait_ready();
printf("ATA: Primary master (hda) initialized\n");
}
void ata_identify(void)
{
static uint16_t buffer[256];
x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0);
x86_64_outb(ATA_PRIMARY_SECCOUNT, 0);
x86_64_outb(ATA_PRIMARY_LBALOW, 0);
x86_64_outb(ATA_PRIMARY_LBAMID, 0);
x86_64_outb(ATA_PRIMARY_LBAHIGH, 0);
x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_IDENTIFY);
if (x86_64_inb(ATA_PRIMARY_STATUS) == 0) {
printf("ATA: No primary master drive detected\n");
return;
}
if (!ata_poll()) {
printf("ATA poll failed at ATA_IDENTIFY\n");
}
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
printf("ATA: Identify error\n");
return;
}
x86_64_insw(ATA_PRIMARY_DATA, buffer, 256);
printf("ATA: Disk model: ");
for (int i = 27; i <= 46; i++) {
uint16_t w = buffer[i];
char high = w >> 8;
char low = w & 0xFF;
printf("%c%c", high, low); // swap bytes
}
printf("\n");
printf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16));
}
bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer)
{
if (sector_count == 0) return true;
ata_wait_ready();
x86_64_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F));
x86_64_outb(ATA_PRIMARY_SECCOUNT, sector_count);
x86_64_outb(ATA_PRIMARY_LBALOW, (uint8_t)lba);
x86_64_outb(ATA_PRIMARY_LBAMID, (uint8_t)(lba >> 8));
x86_64_outb(ATA_PRIMARY_LBAHIGH, (uint8_t)(lba >> 16));
x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_READ_SECTORS);
uint16_t* buf = buffer;
for (uint8_t i = 0; i < sector_count; i++) {
if (!ata_poll()) {
printf("ATA poll failed at ATA_read_sectors\n");
}
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
printf("ATA read error at LBA %lu\n", lba + i);
return false;
}
x86_64_insw(ATA_PRIMARY_DATA, buf, 256); // 512 bytes
buf += 256;
}
return true;
}
bool ata_write_sectors(uint64_t lba, uint8_t sector_count, const void* buffer) {
if (sector_count == 0) return true;
ata_wait_ready();
x86_64_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F));
x86_64_outb(ATA_PRIMARY_SECCOUNT, sector_count);
x86_64_outb(ATA_PRIMARY_LBALOW, (uint8_t)lba);
x86_64_outb(ATA_PRIMARY_LBAMID, (uint8_t)(lba >> 8));
x86_64_outb(ATA_PRIMARY_LBAHIGH, (uint8_t)(lba >> 16));
x86_64_outb(ATA_PRIMARY_COMMAND, 0x30); // write sectors
const uint16_t* buf = buffer;
for (uint8_t i = 0; i < sector_count; i++) {
if (!ata_poll()) {
return false;
}
x86_64_outsw(ATA_PRIMARY_DATA, buf, 256);
buf += 256;
}
return true;
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
void ata_init(void);
void ata_identify(void);
// Read `sector_count` 512-byte sectors starting at LBA `lba` into `buffer`.
// Buffer must be large enough (sector_count * 512).
bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer);
bool ata_write_sectors(uint64_t lba, uint8_t sector_count, const void* buffer);
+13
View File
@@ -0,0 +1,13 @@
#include "e9.h"
#include <arch/x86_64/io.h>
void e9_putc(char c)
{
x86_64_outb(0xE9, c);
}
void e9_puts(const char* str) {
while (*str) {
e9_putc(*str++);
}
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void e9_putc(char c);
+88
View File
@@ -0,0 +1,88 @@
#include "gdt.h"
#include "mm/memory.h"
#include "mp/spinlock.h"
#include <stddef.h>
struct gdt_desc {
uint16_t limit;
uint16_t base_low;
uint8_t base_mid;
uint8_t access;
uint8_t granularity;
uint8_t base_hi;
} __attribute__((packed));
struct tss_desc {
uint16_t length;
uint16_t base_low;
uint8_t base_mid;
uint8_t flags1;
uint8_t flags2;
uint8_t base_hi;
uint32_t base_upper32;
uint32_t reserved;
} __attribute__((packed));
struct gdt_ptr {
uint16_t limit;
uint64_t ptr;
} __attribute__((packed));
struct gdtr {
struct gdt_desc entries[5];
struct tss_desc tss;
} __attribute__((packed));
struct gdtr gdt = {0};
struct gdt_ptr gdt_pointer = {0};
struct tss kernel_tss = {0};
spinlock_t s_gdt_lock = SPINLOCK_INIT;
extern void gdt_reload(void);
extern void tss_reload(void);
void x86_64_GDT_Initialize(void) {
uint64_t flags;
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
// Kernel code
gdt.entries[1].access = 0b10011010;
gdt.entries[1].granularity = 0b00100000;
// Kernel data
gdt.entries[2].access = 0b10010010;
// User data
gdt.entries[3].access = 0b11110010;
// User code
gdt.entries[4].access = 0b11111010;
gdt.entries[4].granularity = 0b00100000;
// TSS
gdt.tss.length = sizeof(struct tss);
gdt.tss.flags1 = 0b10001001;
// Set the pointer
gdt_pointer.limit = sizeof(gdt) - 1;
gdt_pointer.ptr = (uint64_t)&gdt;
gdt_reload();
tss_reload();
spinlock_release_irqrestore(&s_gdt_lock, flags);
}
void gdt_load_tss(size_t addr) {
uint64_t flags;
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
gdt.tss.base_low = (uint16_t)addr;
gdt.tss.base_mid = (uint8_t)(addr >> 16);
gdt.tss.flags1 = 0b10001001;
gdt.tss.base_hi = (uint8_t)(addr >> 24);
gdt.tss.base_upper32 = (uint32_t)(addr >> 32);
tss_reload();
spinlock_release_irqrestore(&s_gdt_lock, flags);
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#define GDT_KERNEL_BASE 0x0
#define GDT_KERNEL_CODE64 0x8
#define GDT_KERNEL_DATA64 0x10
#define GDT_USER_BASE 0x18
#define GDT_USER_DATA64 0x18
#define GDT_USER_CODE64 0x20
#define GDT_TSS 0x28
struct tss {
uint32_t reserved;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t reserved2;
uint64_t ist1;
uint64_t ist2;
uint64_t ist3;
uint64_t ist4;
uint64_t ist5;
uint64_t ist6;
uint64_t ist7;
uint64_t reserved3;
uint16_t reserved4;
uint16_t iomap_base;
} __attribute__((packed));
void x86_64_GDT_Initialize(void);
void gdt_load_tss(size_t addr);
+27
View File
@@ -0,0 +1,27 @@
.intel_syntax noprefix
.global x86_64_GDT_Load
.extern gdt_pointer
.global gdt_reload
gdt_reload:
lgdt [rip + gdt_pointer]
push 8
lea rax, [rip + .flush]
push rax
lretq
.flush:
mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
.global tss_reload
tss_reload:
mov ax, 0x2B
ltr ax
ret
+167
View File
@@ -0,0 +1,167 @@
#include "pic.h"
#include "io.h"
#include <stdbool.h>
#include <stdint.h>
#define PIC1_COMMAND_PORT 0x20
#define PIC1_DATA_PORT 0x21
#define PIC2_COMMAND_PORT 0xA0
#define PIC2_DATA_PORT 0xA1
// Initialization Control Word 1
// -----------------------------
// 0 IC4 if set, the PIC expects to receive ICW4 during initialization
// 1 SGNL if set, only 1 PIC in the system; if unset, the PIC is cascaded with slave PICs
// and ICW3 must be sent to controller
// 2 ADI call address interval, set: 4, not set: 8; ignored on x86, set to 0
// 3 LTIM if set, operate in level triggered mode; if unset, operate in edge triggered mode
// 4 INIT set to 1 to initialize PIC
// 5-7 ignored on x86, set to 0
enum {
PIC_ICW1_ICW4 = 0x01,
PIC_ICW1_SINGLE = 0x02,
PIC_ICW1_INTERVAL4 = 0x04,
PIC_ICW1_LEVEL = 0x08,
PIC_ICW1_INITIALIZE = 0x10
} PIC_ICW1;
// Initialization Control Word 4
// -----------------------------
// 0 uPM if set, PIC is in 80x86 mode; if cleared, in MCS-80/85 mode
// 1 AEOI if set, on last interrupt acknowledge pulse, controller automatically performs
// end of interrupt operation
// 2 M/S only use if BUF is set; if set, selects buffer master; otherwise, selects buffer slave
// 3 BUF if set, controller operates in buffered mode
// 4 SFNM specially fully nested mode; used in systems with large number of cascaded controllers
// 5-7 reserved, set to 0
enum {
PIC_ICW4_8086 = 0x1,
PIC_ICW4_AUTO_EOI = 0x2,
PIC_ICW4_BUFFER_MASTER = 0x4,
PIC_ICW4_BUFFER_SLAVE = 0x0,
PIC_ICW4_BUFFERRED = 0x8,
PIC_ICW4_SFNM = 0x10,
} PIC_ICW4;
enum {
PIC_CMD_END_OF_INTERRUPT = 0x20,
PIC_CMD_READ_IRR = 0x0A,
PIC_CMD_READ_ISR = 0x0B,
} PIC_CMD;
static uint16_t g_PicMask = 0xffff;
static bool g_AutoEoi = false;
void i8259_SetMask(uint16_t newMask)
{
g_PicMask = newMask;
x86_64_outb(PIC1_DATA_PORT, g_PicMask & 0xFF);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, g_PicMask >> 8);
x86_64_iowait();
}
uint16_t i8259_GetMask()
{
return x86_64_inb(PIC1_DATA_PORT) | (x86_64_inb(PIC2_DATA_PORT) << 8);
}
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi)
{
// Mask everything
i8259_SetMask(0xFFFF);
// initialization control word 1
x86_64_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
x86_64_iowait();
x86_64_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
x86_64_iowait();
// initialization control word 2 - the offsets
x86_64_outb(PIC1_DATA_PORT, offsetPic1);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, offsetPic2);
x86_64_iowait();
// initialization control word 3
x86_64_outb(PIC1_DATA_PORT, 0x4); // tell PIC1 that it has a slave at IRQ2 (0000 0100)
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, 0x2); // tell PIC2 its cascade identity (0000 0010)
x86_64_iowait();
// initialization control word 4
uint8_t icw4 = PIC_ICW4_8086;
if (autoEoi) {
icw4 |= PIC_ICW4_AUTO_EOI;
}
x86_64_outb(PIC1_DATA_PORT, icw4);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, icw4);
x86_64_iowait();
// mask all interrupts until they are enabled by the device driver
i8259_SetMask(0xFFFF);
}
void i8259_SendEndOfInterrupt(int irq)
{
if (irq >= 8)
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
}
void i8259_Disable()
{
i8259_SetMask(0xFFFF);
}
void i8259_Mask(int irq)
{
i8259_SetMask(g_PicMask | (1 << irq));
}
void i8259_Unmask(int irq)
{
i8259_SetMask(g_PicMask & ~(1 << irq));
}
uint16_t i8259_ReadIrqRequestRegister()
{
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR);
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR);
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
}
uint16_t i8259_ReadInServiceRegister()
{
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_ISR);
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_ISR);
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
}
bool i8259_Probe()
{
i8259_Disable();
i8259_SetMask(0x1337);
return i8259_GetMask() == 0x1337;
}
static const PICDriver g_PicDriver = {
.Name = "8259 PIC",
.Probe = &i8259_Probe,
.Initialize = &i8259_Configure,
.Disable = &i8259_Disable,
.SendEndOfInterrupt = &i8259_SendEndOfInterrupt,
.Mask = &i8259_Mask,
.Unmask = &i8259_Unmask,
};
const PICDriver* i8259_GetDriver()
{
return &g_PicDriver;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "pic.h"
const PICDriver* i8259_GetDriver();
uint16_t i8259_GetMask();
void i8259_SetMask(uint16_t newMask);
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
+35
View File
@@ -0,0 +1,35 @@
#include "idt.h"
#include "util/binary.h"
IDTEntry g_IDT[256];
IDTDescriptor g_IDTDescriptor = { sizeof(g_IDT) - 1, g_IDT };
extern void x86_64_IDT_Load(IDTDescriptor* descriptor);
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags)
{
uintptr_t addr = (uintptr_t)base;
g_IDT[interrupt].BaseLow = addr & 0xFFFF;
g_IDT[interrupt].SegmentSelector = segmentDescriptor;
g_IDT[interrupt].IST = 0;
g_IDT[interrupt].Flags = flags;
g_IDT[interrupt].BaseMid = (addr >> 16) & 0xFFFF;
g_IDT[interrupt].BaseHigh = (addr >> 32) & 0xFFFFFFFF;
g_IDT[interrupt].Reserved = 0;
}
void x86_64_IDT_EnableGate(int interrupt)
{
FLAG_SET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
}
void x86_64_IDT_DisableGate(int interrupt)
{
FLAG_UNSET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
}
void x86_64_IDT_Initialize(void)
{
x86_64_IDT_Load(&g_IDTDescriptor);
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include <stdint.h>
typedef enum
{
IDT_FLAG_GATE_TASK = 0x5,
IDT_FLAG_GATE_16BIT_INT = 0x6,
IDT_FLAG_GATE_16BIT_TRAP = 0x7,
IDT_FLAG_GATE_32BIT_INT = 0xE,
IDT_FLAG_GATE_32BIT_TRAP = 0xF,
IDT_FLAG_RING0 = (0 << 5),
IDT_FLAG_RING1 = (1 << 5),
IDT_FLAG_RING2 = (2 << 5),
IDT_FLAG_RING3 = (3 << 5),
IDT_FLAG_PRESENT = 0x80,
} IDT_FLAGS;
typedef struct
{
uint16_t BaseLow;
uint16_t SegmentSelector;
uint8_t IST; // Interrupt Stack Table (0 = default)
uint8_t Flags;
uint16_t BaseMid;
uint32_t BaseHigh;
uint32_t Reserved;
} __attribute__((packed)) IDTEntry;
typedef struct
{
uint16_t Limit;
IDTEntry* Ptr;
} __attribute__((packed)) IDTDescriptor;
void x86_64_IDT_Initialize(void);
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags);
void x86_64_IDT_EnableGate(int interrupt);
void x86_64_IDT_DisableGate(int interrupt);
+6
View File
@@ -0,0 +1,6 @@
.intel_syntax noprefix
.global x86_64_IDT_Load
x86_64_IDT_Load:
lidt [rdi] # descriptor in RDI
ret
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
void x86_64_outb(uint16_t port, uint8_t value);
uint8_t x86_64_inb(uint16_t port);
uint16_t x86_64_inw(uint16_t port);
void x86_64_outw(uint16_t port, uint16_t value);
void x86_64_insw(uint16_t port, uint16_t* buffer, uint32_t count);
void x86_64_outl(uint16_t port, uint32_t value);
uint32_t x86_64_inl(uint16_t port);
void x86_64_outsw(uint16_t port, uint16_t* buffer, uint32_t count);
void x86_64_iowait(void);
void x86_64_Panic(void) __attribute__((noreturn));
void x86_64_EnableInterrupts(void);
void x86_64_DisableInterrupts(void);
void x86_64_crashme(void);
+96
View File
@@ -0,0 +1,96 @@
.intel_syntax noprefix
.global x86_64_outb
x86_64_outb:
mov dx, di
mov al, sil
out dx, al
ret
.global x86_64_inb
x86_64_inb:
mov dx, di
xor eax, eax
in al, dx
ret
.global x86_64_inw
x86_64_inw:
mov dx, di
xor eax, eax
in ax, dx
ret
.global x86_64_outw
x86_64_outw:
mov dx, di
mov ax, si
out dx, ax
ret
.global x86_64_outl
x86_64_outl:
mov dx, di
mov eax, esi
out dx, eax
ret
.global x86_64_inl
x86_64_inl:
mov dx, di
xor eax, eax
in eax, dx
ret
.global x86_64_insw
x86_64_insw:
test rdx, rdx
jz .inswdone
mov rcx, rdx
mov dx, di
mov rdi, rsi
cld
rep insw
.inswdone:
ret
.global x86_64_outsw
x86_64_outsw:
test rdx, rdx
jz .outswdone
mov rcx, rdx
mov dx, di
mov rsi, rsi
cld
rep outsw
.outswdone:
ret
.global x86_64_Panic
x86_64_Panic:
cli
hlt
1: jmp 1b
.global x86_64_EnableInterrupts
x86_64_EnableInterrupts:
sti
ret
.global x86_64_DisableInterrupts
x86_64_DisableInterrupts:
cli
ret
.global x86_64_iowait
x86_64_iowait:
out 0x80, al // classic I/O wait
ret
.global x86_64_crashme
x86_64_crashme:
xor rdx, rdx
mov rax, 1
mov rbx, 0
div rbx
ret
+65
View File
@@ -0,0 +1,65 @@
#include "irq.h"
#include "i8259.h"
#include "io.h"
#include <stddef.h>
#include <util/arrays.h>
#include "stdio.h"
#include <debug.h>
#define PIC_REMAP_OFFSET 0x20
#define MODULE "PIC"
IRQHandler g_IRQHandlers[16];
static const PICDriver* g_Driver = NULL;
void x86_64_IRQ_Handler(Registers *regs)
{
int irq = regs->interrupt - PIC_REMAP_OFFSET;
if (g_IRQHandlers[irq] != NULL)
{
// handle IRQ
g_IRQHandlers[irq](regs);
}
else
{
log_warn(MODULE, "Unhandled IRQ %d...", irq);
}
// send EOI
g_Driver->SendEndOfInterrupt(irq);
}
void x86_64_IRQ_Initialize(void)
{
const PICDriver* drivers[] = {
i8259_GetDriver(),
};
for (int i = 0; i < SIZE(drivers); i++) {
if (drivers[i]->Probe()) {
g_Driver = drivers[i];
}
}
if (g_Driver == NULL) {
log_warn(MODULE, "No PIC found!");
return;
}
log_info(MODULE, "Found %s PIC.", g_Driver->Name);
g_Driver->Initialize(PIC_REMAP_OFFSET, PIC_REMAP_OFFSET + 8, false);
// register ISR handlers for each of the 16 irq lines
for (int i = 0; i < 16; i++)
x86_64_ISR_RegisterHandler(PIC_REMAP_OFFSET + i, x86_64_IRQ_Handler);
x86_64_EnableInterrupts();
}
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler)
{
g_IRQHandlers[irq] = handler;
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "isr.h"
typedef void (*IRQHandler)(Registers* regs);
void x86_64_IRQ_Initialize();
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler);
+82
View File
@@ -0,0 +1,82 @@
// ... includes ...
#include "io.h"
#include "debug.h"
#include "arch/x86_64/isr.h"
#include "idt.h"
#define MODULE "ISR"
ISRHandler g_ISRHandlers[256];
static const char* const g_Exceptions[] = {
"Divide by zero error",
"Debug",
"Non-maskable Interrupt",
"Breakpoint",
"Overflow",
"Bound Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
"",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception ",
"",
"",
"",
"",
"",
"",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
""
};
extern void x86_64_ISR_InitializeGates(void); // defined in isrs_gen.c
void x86_64_ISR_Initialize(void)
{
x86_64_ISR_InitializeGates();
for (int i = 0; i < 256; i++)
x86_64_IDT_EnableGate(i);
x86_64_IDT_DisableGate(0x80); // syscall gate if you want
}
void __attribute__((used)) x86_64_ISR_Handler(Registers* regs)
{
if (g_ISRHandlers[regs->interrupt])
g_ISRHandlers[regs->interrupt](regs);
else if (regs->interrupt >= 32)
log_err(MODULE, "Unhandled interrupt %d!", regs->interrupt);
else {
// panic log (use regs->rax etc. now)
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
// ... print registers with rax/rbx etc. ...
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
log_crit(MODULE, "KERNEL PANIC!");
x86_64_Panic();
}
}
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler)
{
g_ISRHandlers[interrupt] = handler;
x86_64_IDT_EnableGate(interrupt);
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
typedef struct
{
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax;
uint64_t interrupt, error;
uint64_t rip, cs, rflags, rsp, ss;
} __attribute__((packed)) Registers;
typedef void (*ISRHandler)(Registers* regs);
void x86_64_ISR_Initialize(void);
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler);
+58
View File
@@ -0,0 +1,58 @@
.intel_syntax noprefix
.extern x86_64_ISR_Handler
.macro ISR_NOERRORCODE num
.global x86_64_ISR\num
x86_64_ISR\num:
push 0
push \num
jmp isr_common
.endm
.macro ISR_ERRORCODE num
.global x86_64_ISR\num
x86_64_ISR\num:
push \num
jmp isr_common
.endm
.include "arch/x86_64/isrs_gen.inc" // update path if needed
isr_common:
push rax
push rbx
push rcx
push rdx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp // Registers* in RDI
call x86_64_ISR_Handler
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 16 // pop interrupt + error code
iretq
+520
View File
@@ -0,0 +1,520 @@
// !!! THIS FILE IS AUTOGENERATED !!!
#include "idt.h"
#include "gdt.h"
void x86_64_ISR0();
void x86_64_ISR1();
void x86_64_ISR2();
void x86_64_ISR3();
void x86_64_ISR4();
void x86_64_ISR5();
void x86_64_ISR6();
void x86_64_ISR7();
void x86_64_ISR8();
void x86_64_ISR9();
void x86_64_ISR10();
void x86_64_ISR11();
void x86_64_ISR12();
void x86_64_ISR13();
void x86_64_ISR14();
void x86_64_ISR15();
void x86_64_ISR16();
void x86_64_ISR17();
void x86_64_ISR18();
void x86_64_ISR19();
void x86_64_ISR20();
void x86_64_ISR21();
void x86_64_ISR22();
void x86_64_ISR23();
void x86_64_ISR24();
void x86_64_ISR25();
void x86_64_ISR26();
void x86_64_ISR27();
void x86_64_ISR28();
void x86_64_ISR29();
void x86_64_ISR30();
void x86_64_ISR31();
void x86_64_ISR32();
void x86_64_ISR33();
void x86_64_ISR34();
void x86_64_ISR35();
void x86_64_ISR36();
void x86_64_ISR37();
void x86_64_ISR38();
void x86_64_ISR39();
void x86_64_ISR40();
void x86_64_ISR41();
void x86_64_ISR42();
void x86_64_ISR43();
void x86_64_ISR44();
void x86_64_ISR45();
void x86_64_ISR46();
void x86_64_ISR47();
void x86_64_ISR48();
void x86_64_ISR49();
void x86_64_ISR50();
void x86_64_ISR51();
void x86_64_ISR52();
void x86_64_ISR53();
void x86_64_ISR54();
void x86_64_ISR55();
void x86_64_ISR56();
void x86_64_ISR57();
void x86_64_ISR58();
void x86_64_ISR59();
void x86_64_ISR60();
void x86_64_ISR61();
void x86_64_ISR62();
void x86_64_ISR63();
void x86_64_ISR64();
void x86_64_ISR65();
void x86_64_ISR66();
void x86_64_ISR67();
void x86_64_ISR68();
void x86_64_ISR69();
void x86_64_ISR70();
void x86_64_ISR71();
void x86_64_ISR72();
void x86_64_ISR73();
void x86_64_ISR74();
void x86_64_ISR75();
void x86_64_ISR76();
void x86_64_ISR77();
void x86_64_ISR78();
void x86_64_ISR79();
void x86_64_ISR80();
void x86_64_ISR81();
void x86_64_ISR82();
void x86_64_ISR83();
void x86_64_ISR84();
void x86_64_ISR85();
void x86_64_ISR86();
void x86_64_ISR87();
void x86_64_ISR88();
void x86_64_ISR89();
void x86_64_ISR90();
void x86_64_ISR91();
void x86_64_ISR92();
void x86_64_ISR93();
void x86_64_ISR94();
void x86_64_ISR95();
void x86_64_ISR96();
void x86_64_ISR97();
void x86_64_ISR98();
void x86_64_ISR99();
void x86_64_ISR100();
void x86_64_ISR101();
void x86_64_ISR102();
void x86_64_ISR103();
void x86_64_ISR104();
void x86_64_ISR105();
void x86_64_ISR106();
void x86_64_ISR107();
void x86_64_ISR108();
void x86_64_ISR109();
void x86_64_ISR110();
void x86_64_ISR111();
void x86_64_ISR112();
void x86_64_ISR113();
void x86_64_ISR114();
void x86_64_ISR115();
void x86_64_ISR116();
void x86_64_ISR117();
void x86_64_ISR118();
void x86_64_ISR119();
void x86_64_ISR120();
void x86_64_ISR121();
void x86_64_ISR122();
void x86_64_ISR123();
void x86_64_ISR124();
void x86_64_ISR125();
void x86_64_ISR126();
void x86_64_ISR127();
void x86_64_ISR128();
void x86_64_ISR129();
void x86_64_ISR130();
void x86_64_ISR131();
void x86_64_ISR132();
void x86_64_ISR133();
void x86_64_ISR134();
void x86_64_ISR135();
void x86_64_ISR136();
void x86_64_ISR137();
void x86_64_ISR138();
void x86_64_ISR139();
void x86_64_ISR140();
void x86_64_ISR141();
void x86_64_ISR142();
void x86_64_ISR143();
void x86_64_ISR144();
void x86_64_ISR145();
void x86_64_ISR146();
void x86_64_ISR147();
void x86_64_ISR148();
void x86_64_ISR149();
void x86_64_ISR150();
void x86_64_ISR151();
void x86_64_ISR152();
void x86_64_ISR153();
void x86_64_ISR154();
void x86_64_ISR155();
void x86_64_ISR156();
void x86_64_ISR157();
void x86_64_ISR158();
void x86_64_ISR159();
void x86_64_ISR160();
void x86_64_ISR161();
void x86_64_ISR162();
void x86_64_ISR163();
void x86_64_ISR164();
void x86_64_ISR165();
void x86_64_ISR166();
void x86_64_ISR167();
void x86_64_ISR168();
void x86_64_ISR169();
void x86_64_ISR170();
void x86_64_ISR171();
void x86_64_ISR172();
void x86_64_ISR173();
void x86_64_ISR174();
void x86_64_ISR175();
void x86_64_ISR176();
void x86_64_ISR177();
void x86_64_ISR178();
void x86_64_ISR179();
void x86_64_ISR180();
void x86_64_ISR181();
void x86_64_ISR182();
void x86_64_ISR183();
void x86_64_ISR184();
void x86_64_ISR185();
void x86_64_ISR186();
void x86_64_ISR187();
void x86_64_ISR188();
void x86_64_ISR189();
void x86_64_ISR190();
void x86_64_ISR191();
void x86_64_ISR192();
void x86_64_ISR193();
void x86_64_ISR194();
void x86_64_ISR195();
void x86_64_ISR196();
void x86_64_ISR197();
void x86_64_ISR198();
void x86_64_ISR199();
void x86_64_ISR200();
void x86_64_ISR201();
void x86_64_ISR202();
void x86_64_ISR203();
void x86_64_ISR204();
void x86_64_ISR205();
void x86_64_ISR206();
void x86_64_ISR207();
void x86_64_ISR208();
void x86_64_ISR209();
void x86_64_ISR210();
void x86_64_ISR211();
void x86_64_ISR212();
void x86_64_ISR213();
void x86_64_ISR214();
void x86_64_ISR215();
void x86_64_ISR216();
void x86_64_ISR217();
void x86_64_ISR218();
void x86_64_ISR219();
void x86_64_ISR220();
void x86_64_ISR221();
void x86_64_ISR222();
void x86_64_ISR223();
void x86_64_ISR224();
void x86_64_ISR225();
void x86_64_ISR226();
void x86_64_ISR227();
void x86_64_ISR228();
void x86_64_ISR229();
void x86_64_ISR230();
void x86_64_ISR231();
void x86_64_ISR232();
void x86_64_ISR233();
void x86_64_ISR234();
void x86_64_ISR235();
void x86_64_ISR236();
void x86_64_ISR237();
void x86_64_ISR238();
void x86_64_ISR239();
void x86_64_ISR240();
void x86_64_ISR241();
void x86_64_ISR242();
void x86_64_ISR243();
void x86_64_ISR244();
void x86_64_ISR245();
void x86_64_ISR246();
void x86_64_ISR247();
void x86_64_ISR248();
void x86_64_ISR249();
void x86_64_ISR250();
void x86_64_ISR251();
void x86_64_ISR252();
void x86_64_ISR253();
void x86_64_ISR254();
void x86_64_ISR255();
void x86_64_ISR_InitializeGates()
{
x86_64_IDT_SetGate(0, x86_64_ISR0, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(1, x86_64_ISR1, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(2, x86_64_ISR2, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(3, x86_64_ISR3, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(4, x86_64_ISR4, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(5, x86_64_ISR5, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(6, x86_64_ISR6, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(7, x86_64_ISR7, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(8, x86_64_ISR8, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(9, x86_64_ISR9, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(10, x86_64_ISR10, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(11, x86_64_ISR11, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(12, x86_64_ISR12, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(13, x86_64_ISR13, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(14, x86_64_ISR14, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(15, x86_64_ISR15, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(16, x86_64_ISR16, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(17, x86_64_ISR17, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(18, x86_64_ISR18, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(19, x86_64_ISR19, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(20, x86_64_ISR20, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(21, x86_64_ISR21, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(22, x86_64_ISR22, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(23, x86_64_ISR23, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(24, x86_64_ISR24, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(25, x86_64_ISR25, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(26, x86_64_ISR26, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(27, x86_64_ISR27, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(28, x86_64_ISR28, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(29, x86_64_ISR29, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(30, x86_64_ISR30, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(31, x86_64_ISR31, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(32, x86_64_ISR32, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(33, x86_64_ISR33, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(34, x86_64_ISR34, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(35, x86_64_ISR35, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(36, x86_64_ISR36, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(37, x86_64_ISR37, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(38, x86_64_ISR38, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(39, x86_64_ISR39, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(40, x86_64_ISR40, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(41, x86_64_ISR41, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(42, x86_64_ISR42, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(43, x86_64_ISR43, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(44, x86_64_ISR44, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(45, x86_64_ISR45, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(46, x86_64_ISR46, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(47, x86_64_ISR47, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(48, x86_64_ISR48, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(49, x86_64_ISR49, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(50, x86_64_ISR50, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(51, x86_64_ISR51, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(52, x86_64_ISR52, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(53, x86_64_ISR53, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(54, x86_64_ISR54, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(55, x86_64_ISR55, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(56, x86_64_ISR56, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(57, x86_64_ISR57, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(58, x86_64_ISR58, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(59, x86_64_ISR59, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(60, x86_64_ISR60, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(61, x86_64_ISR61, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(62, x86_64_ISR62, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(63, x86_64_ISR63, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(64, x86_64_ISR64, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(65, x86_64_ISR65, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(66, x86_64_ISR66, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(67, x86_64_ISR67, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(68, x86_64_ISR68, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(69, x86_64_ISR69, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(70, x86_64_ISR70, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(71, x86_64_ISR71, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(72, x86_64_ISR72, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(73, x86_64_ISR73, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(74, x86_64_ISR74, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(75, x86_64_ISR75, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(76, x86_64_ISR76, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(77, x86_64_ISR77, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(78, x86_64_ISR78, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(79, x86_64_ISR79, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(80, x86_64_ISR80, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(81, x86_64_ISR81, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(82, x86_64_ISR82, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(83, x86_64_ISR83, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(84, x86_64_ISR84, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(85, x86_64_ISR85, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(86, x86_64_ISR86, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(87, x86_64_ISR87, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(88, x86_64_ISR88, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(89, x86_64_ISR89, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(90, x86_64_ISR90, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(91, x86_64_ISR91, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(92, x86_64_ISR92, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(93, x86_64_ISR93, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(94, x86_64_ISR94, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(95, x86_64_ISR95, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(96, x86_64_ISR96, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(97, x86_64_ISR97, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(98, x86_64_ISR98, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(99, x86_64_ISR99, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(100, x86_64_ISR100, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(101, x86_64_ISR101, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(102, x86_64_ISR102, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(103, x86_64_ISR103, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(104, x86_64_ISR104, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(105, x86_64_ISR105, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(106, x86_64_ISR106, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(107, x86_64_ISR107, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(108, x86_64_ISR108, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(109, x86_64_ISR109, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(110, x86_64_ISR110, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(111, x86_64_ISR111, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(112, x86_64_ISR112, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(113, x86_64_ISR113, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(114, x86_64_ISR114, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(115, x86_64_ISR115, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(116, x86_64_ISR116, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(117, x86_64_ISR117, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(118, x86_64_ISR118, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(119, x86_64_ISR119, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(120, x86_64_ISR120, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(121, x86_64_ISR121, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(122, x86_64_ISR122, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(123, x86_64_ISR123, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(124, x86_64_ISR124, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(125, x86_64_ISR125, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(126, x86_64_ISR126, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(127, x86_64_ISR127, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(128, x86_64_ISR128, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(129, x86_64_ISR129, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(130, x86_64_ISR130, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(131, x86_64_ISR131, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(132, x86_64_ISR132, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(133, x86_64_ISR133, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(134, x86_64_ISR134, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(135, x86_64_ISR135, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(136, x86_64_ISR136, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(137, x86_64_ISR137, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(138, x86_64_ISR138, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(139, x86_64_ISR139, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(140, x86_64_ISR140, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(141, x86_64_ISR141, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(142, x86_64_ISR142, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(143, x86_64_ISR143, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(144, x86_64_ISR144, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(145, x86_64_ISR145, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(146, x86_64_ISR146, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(147, x86_64_ISR147, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(148, x86_64_ISR148, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(149, x86_64_ISR149, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(150, x86_64_ISR150, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(151, x86_64_ISR151, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(152, x86_64_ISR152, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(153, x86_64_ISR153, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(154, x86_64_ISR154, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(155, x86_64_ISR155, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(156, x86_64_ISR156, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(157, x86_64_ISR157, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(158, x86_64_ISR158, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(159, x86_64_ISR159, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(160, x86_64_ISR160, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(161, x86_64_ISR161, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(162, x86_64_ISR162, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(163, x86_64_ISR163, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(164, x86_64_ISR164, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(165, x86_64_ISR165, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(166, x86_64_ISR166, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(167, x86_64_ISR167, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(168, x86_64_ISR168, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(169, x86_64_ISR169, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(170, x86_64_ISR170, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(171, x86_64_ISR171, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(172, x86_64_ISR172, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(173, x86_64_ISR173, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(174, x86_64_ISR174, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(175, x86_64_ISR175, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(176, x86_64_ISR176, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(177, x86_64_ISR177, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(178, x86_64_ISR178, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(179, x86_64_ISR179, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(180, x86_64_ISR180, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(181, x86_64_ISR181, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(182, x86_64_ISR182, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(183, x86_64_ISR183, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(184, x86_64_ISR184, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(185, x86_64_ISR185, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(186, x86_64_ISR186, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(187, x86_64_ISR187, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(188, x86_64_ISR188, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(189, x86_64_ISR189, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(190, x86_64_ISR190, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(191, x86_64_ISR191, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(192, x86_64_ISR192, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(193, x86_64_ISR193, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(194, x86_64_ISR194, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(195, x86_64_ISR195, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(196, x86_64_ISR196, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(197, x86_64_ISR197, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(198, x86_64_ISR198, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(199, x86_64_ISR199, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(200, x86_64_ISR200, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(201, x86_64_ISR201, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(202, x86_64_ISR202, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(203, x86_64_ISR203, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(204, x86_64_ISR204, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(205, x86_64_ISR205, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(206, x86_64_ISR206, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(207, x86_64_ISR207, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(208, x86_64_ISR208, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(209, x86_64_ISR209, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(210, x86_64_ISR210, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(211, x86_64_ISR211, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(212, x86_64_ISR212, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(213, x86_64_ISR213, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(214, x86_64_ISR214, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(215, x86_64_ISR215, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(216, x86_64_ISR216, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(217, x86_64_ISR217, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(218, x86_64_ISR218, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(219, x86_64_ISR219, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(220, x86_64_ISR220, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(221, x86_64_ISR221, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(222, x86_64_ISR222, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(223, x86_64_ISR223, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(224, x86_64_ISR224, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(225, x86_64_ISR225, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(226, x86_64_ISR226, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(227, x86_64_ISR227, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(228, x86_64_ISR228, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(229, x86_64_ISR229, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(230, x86_64_ISR230, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(231, x86_64_ISR231, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(232, x86_64_ISR232, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(233, x86_64_ISR233, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(234, x86_64_ISR234, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(235, x86_64_ISR235, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(236, x86_64_ISR236, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(237, x86_64_ISR237, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(238, x86_64_ISR238, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(239, x86_64_ISR239, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(240, x86_64_ISR240, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(241, x86_64_ISR241, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(242, x86_64_ISR242, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(243, x86_64_ISR243, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(244, x86_64_ISR244, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(245, x86_64_ISR245, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(246, x86_64_ISR246, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(247, x86_64_ISR247, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(248, x86_64_ISR248, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(249, x86_64_ISR249, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(250, x86_64_ISR250, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(251, x86_64_ISR251, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(252, x86_64_ISR252, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(253, x86_64_ISR253, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(254, x86_64_ISR254, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(255, x86_64_ISR255, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
}
+256
View File
@@ -0,0 +1,256 @@
ISR_NOERRORCODE 0
ISR_NOERRORCODE 1
ISR_NOERRORCODE 2
ISR_NOERRORCODE 3
ISR_NOERRORCODE 4
ISR_NOERRORCODE 5
ISR_NOERRORCODE 6
ISR_NOERRORCODE 7
ISR_ERRORCODE 8
ISR_NOERRORCODE 9
ISR_ERRORCODE 10
ISR_ERRORCODE 11
ISR_ERRORCODE 12
ISR_ERRORCODE 13
ISR_ERRORCODE 14
ISR_NOERRORCODE 15
ISR_NOERRORCODE 16
ISR_ERRORCODE 17
ISR_NOERRORCODE 18
ISR_NOERRORCODE 19
ISR_NOERRORCODE 20
ISR_ERRORCODE 21
ISR_NOERRORCODE 22
ISR_NOERRORCODE 23
ISR_NOERRORCODE 24
ISR_NOERRORCODE 25
ISR_NOERRORCODE 26
ISR_NOERRORCODE 27
ISR_NOERRORCODE 28
ISR_NOERRORCODE 29
ISR_NOERRORCODE 30
ISR_NOERRORCODE 31
ISR_NOERRORCODE 32
ISR_NOERRORCODE 33
ISR_NOERRORCODE 34
ISR_NOERRORCODE 35
ISR_NOERRORCODE 36
ISR_NOERRORCODE 37
ISR_NOERRORCODE 38
ISR_NOERRORCODE 39
ISR_NOERRORCODE 40
ISR_NOERRORCODE 41
ISR_NOERRORCODE 42
ISR_NOERRORCODE 43
ISR_NOERRORCODE 44
ISR_NOERRORCODE 45
ISR_NOERRORCODE 46
ISR_NOERRORCODE 47
ISR_NOERRORCODE 48
ISR_NOERRORCODE 49
ISR_NOERRORCODE 50
ISR_NOERRORCODE 51
ISR_NOERRORCODE 52
ISR_NOERRORCODE 53
ISR_NOERRORCODE 54
ISR_NOERRORCODE 55
ISR_NOERRORCODE 56
ISR_NOERRORCODE 57
ISR_NOERRORCODE 58
ISR_NOERRORCODE 59
ISR_NOERRORCODE 60
ISR_NOERRORCODE 61
ISR_NOERRORCODE 62
ISR_NOERRORCODE 63
ISR_NOERRORCODE 64
ISR_NOERRORCODE 65
ISR_NOERRORCODE 66
ISR_NOERRORCODE 67
ISR_NOERRORCODE 68
ISR_NOERRORCODE 69
ISR_NOERRORCODE 70
ISR_NOERRORCODE 71
ISR_NOERRORCODE 72
ISR_NOERRORCODE 73
ISR_NOERRORCODE 74
ISR_NOERRORCODE 75
ISR_NOERRORCODE 76
ISR_NOERRORCODE 77
ISR_NOERRORCODE 78
ISR_NOERRORCODE 79
ISR_NOERRORCODE 80
ISR_NOERRORCODE 81
ISR_NOERRORCODE 82
ISR_NOERRORCODE 83
ISR_NOERRORCODE 84
ISR_NOERRORCODE 85
ISR_NOERRORCODE 86
ISR_NOERRORCODE 87
ISR_NOERRORCODE 88
ISR_NOERRORCODE 89
ISR_NOERRORCODE 90
ISR_NOERRORCODE 91
ISR_NOERRORCODE 92
ISR_NOERRORCODE 93
ISR_NOERRORCODE 94
ISR_NOERRORCODE 95
ISR_NOERRORCODE 96
ISR_NOERRORCODE 97
ISR_NOERRORCODE 98
ISR_NOERRORCODE 99
ISR_NOERRORCODE 100
ISR_NOERRORCODE 101
ISR_NOERRORCODE 102
ISR_NOERRORCODE 103
ISR_NOERRORCODE 104
ISR_NOERRORCODE 105
ISR_NOERRORCODE 106
ISR_NOERRORCODE 107
ISR_NOERRORCODE 108
ISR_NOERRORCODE 109
ISR_NOERRORCODE 110
ISR_NOERRORCODE 111
ISR_NOERRORCODE 112
ISR_NOERRORCODE 113
ISR_NOERRORCODE 114
ISR_NOERRORCODE 115
ISR_NOERRORCODE 116
ISR_NOERRORCODE 117
ISR_NOERRORCODE 118
ISR_NOERRORCODE 119
ISR_NOERRORCODE 120
ISR_NOERRORCODE 121
ISR_NOERRORCODE 122
ISR_NOERRORCODE 123
ISR_NOERRORCODE 124
ISR_NOERRORCODE 125
ISR_NOERRORCODE 126
ISR_NOERRORCODE 127
ISR_NOERRORCODE 128
ISR_NOERRORCODE 129
ISR_NOERRORCODE 130
ISR_NOERRORCODE 131
ISR_NOERRORCODE 132
ISR_NOERRORCODE 133
ISR_NOERRORCODE 134
ISR_NOERRORCODE 135
ISR_NOERRORCODE 136
ISR_NOERRORCODE 137
ISR_NOERRORCODE 138
ISR_NOERRORCODE 139
ISR_NOERRORCODE 140
ISR_NOERRORCODE 141
ISR_NOERRORCODE 142
ISR_NOERRORCODE 143
ISR_NOERRORCODE 144
ISR_NOERRORCODE 145
ISR_NOERRORCODE 146
ISR_NOERRORCODE 147
ISR_NOERRORCODE 148
ISR_NOERRORCODE 149
ISR_NOERRORCODE 150
ISR_NOERRORCODE 151
ISR_NOERRORCODE 152
ISR_NOERRORCODE 153
ISR_NOERRORCODE 154
ISR_NOERRORCODE 155
ISR_NOERRORCODE 156
ISR_NOERRORCODE 157
ISR_NOERRORCODE 158
ISR_NOERRORCODE 159
ISR_NOERRORCODE 160
ISR_NOERRORCODE 161
ISR_NOERRORCODE 162
ISR_NOERRORCODE 163
ISR_NOERRORCODE 164
ISR_NOERRORCODE 165
ISR_NOERRORCODE 166
ISR_NOERRORCODE 167
ISR_NOERRORCODE 168
ISR_NOERRORCODE 169
ISR_NOERRORCODE 170
ISR_NOERRORCODE 171
ISR_NOERRORCODE 172
ISR_NOERRORCODE 173
ISR_NOERRORCODE 174
ISR_NOERRORCODE 175
ISR_NOERRORCODE 176
ISR_NOERRORCODE 177
ISR_NOERRORCODE 178
ISR_NOERRORCODE 179
ISR_NOERRORCODE 180
ISR_NOERRORCODE 181
ISR_NOERRORCODE 182
ISR_NOERRORCODE 183
ISR_NOERRORCODE 184
ISR_NOERRORCODE 185
ISR_NOERRORCODE 186
ISR_NOERRORCODE 187
ISR_NOERRORCODE 188
ISR_NOERRORCODE 189
ISR_NOERRORCODE 190
ISR_NOERRORCODE 191
ISR_NOERRORCODE 192
ISR_NOERRORCODE 193
ISR_NOERRORCODE 194
ISR_NOERRORCODE 195
ISR_NOERRORCODE 196
ISR_NOERRORCODE 197
ISR_NOERRORCODE 198
ISR_NOERRORCODE 199
ISR_NOERRORCODE 200
ISR_NOERRORCODE 201
ISR_NOERRORCODE 202
ISR_NOERRORCODE 203
ISR_NOERRORCODE 204
ISR_NOERRORCODE 205
ISR_NOERRORCODE 206
ISR_NOERRORCODE 207
ISR_NOERRORCODE 208
ISR_NOERRORCODE 209
ISR_NOERRORCODE 210
ISR_NOERRORCODE 211
ISR_NOERRORCODE 212
ISR_NOERRORCODE 213
ISR_NOERRORCODE 214
ISR_NOERRORCODE 215
ISR_NOERRORCODE 216
ISR_NOERRORCODE 217
ISR_NOERRORCODE 218
ISR_NOERRORCODE 219
ISR_NOERRORCODE 220
ISR_NOERRORCODE 221
ISR_NOERRORCODE 222
ISR_NOERRORCODE 223
ISR_NOERRORCODE 224
ISR_NOERRORCODE 225
ISR_NOERRORCODE 226
ISR_NOERRORCODE 227
ISR_NOERRORCODE 228
ISR_NOERRORCODE 229
ISR_NOERRORCODE 230
ISR_NOERRORCODE 231
ISR_NOERRORCODE 232
ISR_NOERRORCODE 233
ISR_NOERRORCODE 234
ISR_NOERRORCODE 235
ISR_NOERRORCODE 236
ISR_NOERRORCODE 237
ISR_NOERRORCODE 238
ISR_NOERRORCODE 239
ISR_NOERRORCODE 240
ISR_NOERRORCODE 241
ISR_NOERRORCODE 242
ISR_NOERRORCODE 243
ISR_NOERRORCODE 244
ISR_NOERRORCODE 245
ISR_NOERRORCODE 246
ISR_NOERRORCODE 247
ISR_NOERRORCODE 248
ISR_NOERRORCODE 249
ISR_NOERRORCODE 250
ISR_NOERRORCODE 251
ISR_NOERRORCODE 252
ISR_NOERRORCODE 253
ISR_NOERRORCODE 254
ISR_NOERRORCODE 255
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef struct {
const char* Name;
bool (*Probe)();
void (*Initialize)(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
void (*Disable)();
void (*SendEndOfInterrupt)(int irq);
void (*Mask)(int irq);
void (*Unmask)(int irq);
} PICDriver;
+104
View File
@@ -0,0 +1,104 @@
#include <stdint.h>
#include <string.h>
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "mm/memory.h"
#include "stdio.h"
#include "fs/elf.h"
extern uintptr_t g_hhdm_offset;
#define USER_STACK_TOP 0x00007FFFFFFFE000ULL
#define USER_STACK_PAGES 4
#define USER_STACK_SIZE (USER_STACK_PAGES * PAGE_SIZE)
#define PTE_PRESENT (1ULL << 0)
#define PTE_WRITABLE (1ULL << 1)
#define PTE_USER (1ULL << 2)
static uint64_t user_stack_phys_base = 0;
extern struct pagemap *kernel_pagemap;
static void setup_user_stack()
{
// Allocate contiguous physical pages for the stack
user_stack_phys_base = (uint64_t)pmm_alloc(USER_STACK_PAGES);
if (!user_stack_phys_base) {
printf("Failed to allocate user stack pages!\n");
for (;;);
}
// Map each page individually into the current pagemap
// Stack grows downward, so start from the bottom
uintptr_t virt = USER_STACK_TOP - USER_STACK_SIZE;
for (int i = 0; i < USER_STACK_PAGES; i++) {
uint64_t phys = user_stack_phys_base + (i * PAGE_SIZE);
bool success = vmm_map_page(
kernel_pagemap, // Use kernel_pagemap for now (later: process->process_pagemap)
virt,
phys,
PAGE_READ | PAGE_WRITE | PAGE_USER, // RW + User
Size4KiB
);
if (!success) {
printf("Failed to map user stack page at 0x%lx\n", virt);
// TODO: cleanup previous pages if partial failure
for (;;);
}
virt += PAGE_SIZE;
}
// Optional: zero the stack (good practice)
// memset((void*)(USER_STACK_TOP - USER_STACK_SIZE), 0, USER_STACK_SIZE);
}
// usermode.c
__attribute__((naked))
void enter_user_mode(uint64_t rip, uint64_t rsp)
{
asm volatile(
"cli\n"
"mov $0x1B, %ax\n" // Use User Data Selector (0x1B)
"mov %ax, %ds\n"
"mov %ax, %es\n"
"mov %ax, %fs\n"
"mov %ax, %gs\n"
"pushq $0x1B\n" // SS (User Data)
"pushq %rsi\n" // RSP
"pushfq\n"
// Optional: manually set IF bit in pushed RFLAGS if you want interrupts enabled
"pop %rax\n"
"or $0x200, %rax\n"
"push %rax\n"
"pushq $0x23\n" // CS (User Code)
"pushq %rdi\n" // RIP
"iretq\n"
);
}
void start_userspace(void)
{
void *entry = NULL;
if (!ELF_Read("init.elf", &entry)) {
printf("Failed to load init.elf\n");
for(;;);
}
setup_user_stack();
printf("Jumping to user entry: 0x%lx with stack top 0x%lx\n",
(uint64_t)entry, USER_STACK_TOP);
enter_user_mode((uint64_t)entry, USER_STACK_TOP);
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include <stdint.h>
void start_userspace(void);
+34
View File
@@ -0,0 +1,34 @@
#include "debug.h"
#include <stdint.h>
#include "stdio.h"
#include <stdarg.h>
static const uint32_t g_LogSeverityColors[] =
{
[LVL_DEBUG] = 0xAAAAAA, // light gray
[LVL_INFO] = 0xFFFFFF, // white
[LVL_WARN] = 0xFFFF00, // yellow
[LVL_ERROR] = 0xFF0000, // red
[LVL_CRITICAL] = 0xFFFFFF, // white (can do red background separately if you want)
};
static const char* const g_ColorReset = "\033[0m";
void logf(const char* module, DebugLevel level, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
uint32_t color = g_LogSeverityColors[level];
fputs_colored("[", color);
fputs_colored(module, color);
fputs_colored("] ", color);
// print formatted text in same color
vfprintf(fmt, args); // or adapt vfprintf to take a color
fputc('\n');
va_end(args);
}
+20
View File
@@ -0,0 +1,20 @@
#include <stdio.h>
#define MIN_LOG_LEVEL LVL_DEBUG
typedef enum {
LVL_DEBUG = 0,
LVL_INFO = 1,
LVL_WARN = 2,
LVL_ERROR = 3,
LVL_CRITICAL = 4
} DebugLevel;
void logf(const char* module, DebugLevel level, const char* fmt, ...);
#define log_debug(module, ...) logf(module, LVL_DEBUG, __VA_ARGS__)
#define log_info(module, ...) logf(module, LVL_INFO, __VA_ARGS__)
#define log_warn(module, ...) logf(module, LVL_WARN, __VA_ARGS__)
#define log_err(module, ...) logf(module, LVL_ERROR, __VA_ARGS__)
#define log_crit(module, ...) logf(module, LVL_CRITICAL, __VA_ARGS__)
+146
View File
@@ -0,0 +1,146 @@
#include "elf.h"
#include "stdio.h"
#include "string.h"
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "mm/memory.h"
#include "fs/ext2.h"
extern uintptr_t g_hhdm_offset;
extern struct pagemap *kernel_pagemap;
#define ELF_BUFFER_SIZE (1024 * 1024)
#define PTE_PRESENT (1ULL << 0)
#define PTE_WRITABLE (1ULL << 1)
#define PTE_USER (1ULL << 2)
bool ELF_Read(const char* path, void** entryPoint)
{
uint32_t size;
uint8_t* elf_buffer = kmalloc(ELF_BUFFER_SIZE);
if (!elf_buffer) {
printf("ELF: kmalloc failed\n");
return false;
}
// ── load file ─────────────────────────────────────
if (!ext2_read_file_from_root(path, elf_buffer, &size)) {
printf("ELF: failed to read file\n");
kfree(elf_buffer);
return false;
}
if (size < sizeof(ELFHeader)) {
printf("ELF: file too small\n");
kfree(elf_buffer);
return false;
}
ELFHeader* header = (ELFHeader*)elf_buffer;
// ── validate ELF ──────────────────────────────────
if (memcmp(header->Magic, ELF_MAGIC, 4) != 0) {
printf("ELF: bad magic\n");
kfree(elf_buffer);
return false;
}
if (header->Bitness != ELF_BITNESS_64BIT) {
printf("ELF: not 64-bit\n");
kfree(elf_buffer);
return false;
}
if (header->Endianness != ELF_ENDIANNESS_LITTLE) {
printf("ELF: wrong endianness\n");
kfree(elf_buffer);
return false;
}
if (header->Type != ELF_TYPE_EXECUTABLE) {
printf("ELF: not executable\n");
kfree(elf_buffer);
return false;
}
if (header->InstructionSet != ELF_INSTRUCTION_SET_X64) {
printf("ELF: wrong arch\n");
kfree(elf_buffer);
return false;
}
*entryPoint = (void*)header->ProgramEntryPosition;
// ── program headers ───────────────────────────────
uint8_t* ph_table = elf_buffer + header->ProgramHeaderTablePosition;
for (uint32_t i = 0; i < header->ProgramHeaderTableEntryCount; i++)
{
ELFProgramHeader* ph = (ELFProgramHeader*)(ph_table +
i * header->ProgramHeaderTableEntrySize);
if (ph->Type != ELF_PROGRAM_TYPE_LOAD)
continue;
uint64_t virt = ph->VirtualAddress;
uint64_t offset = ph->Offset;
uint64_t memsz = ph->MemorySize;
uint64_t filesz = ph->FileSize;
if (memsz == 0)
continue;
// ── align to page boundary ─────────────────────
uint64_t aligned_virt = ALIGN_DOWN(virt, PAGE_SIZE);
uint64_t page_offset = virt & 0xFFF;
uint64_t aligned_memsz = ALIGN_UP(memsz + page_offset, PAGE_SIZE);
uint64_t pages = aligned_memsz / PAGE_SIZE;
// Allocate physical pages
uint64_t phys_base = (uint64_t)pmm_alloc(pages);
if (!phys_base) {
printf("ELF: pmm_alloc failed for %lu pages\n", pages);
kfree(elf_buffer);
return false;
}
// ── map each page individually using new vmm_map_page ─────
for (uint64_t p = 0; p < pages; p++) {
uint64_t virt_addr = aligned_virt + p * PAGE_SIZE;
uint64_t phys_addr = phys_base + p * PAGE_SIZE;
bool success = vmm_map_page(
kernel_pagemap,
virt_addr,
phys_addr,
PAGE_READ | PAGE_WRITE | PAGE_USER, // RW + User mode
Size4KiB
);
if (!success) {
printf("ELF: failed to map page at 0x%lx\n", virt_addr);
// TODO: cleanup previously mapped pages + free phys
kfree(elf_buffer);
return false;
}
}
// ── copy segment data ───────────────────────────────
uint8_t* dst = (uint8_t*)(phys_base + MEM_PHYS_OFFSET); // via HHDM
uint8_t* src = elf_buffer + offset;
memcpy(dst + page_offset, src, filesz);
// ── zero BSS section ────────────────────────────────
if (memsz > filesz) {
memset(dst + page_offset + filesz, 0, memsz - filesz);
}
}
kfree(elf_buffer);
return true;
}
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#define ELF_MAGIC ("\x7F" "ELF")
#include <stdint.h>
typedef struct
{
uint8_t Magic[4];
uint8_t Bitness; // 1 = 32-bit, 2 = 64-bit
uint8_t Endianness; // 1 = little, 2 = big
uint8_t ELFHeaderVersion;
uint8_t ABI;
uint8_t ABIVersion;
uint8_t _Padding[7];
uint16_t Type; // relocatable, executable, shared, core
uint16_t InstructionSet; // architecture (was too small for real ELF, but kept)
uint32_t ELFVersion;
uint64_t ProgramEntryPosition; // FIXED (was 32-bit)
uint64_t ProgramHeaderTablePosition; // FIXED
uint64_t SectionHeaderTablePosition; // FIXED
uint32_t Flags;
uint16_t HeaderSize;
uint16_t ProgramHeaderTableEntrySize;
uint16_t ProgramHeaderTableEntryCount;
uint16_t SectionHeaderTableEntrySize;
uint16_t SectionHeaderTableEntryCount;
uint16_t SectionNamesIndex;
} __attribute__((packed)) ELFHeader;
enum ELFBitness
{
ELF_BITNESS_32BIT = 1,
ELF_BITNESS_64BIT = 2,
};
enum ELFEndianness
{
ELF_ENDIANNESS_LITTLE = 1,
ELF_ENDIANNESS_BIG = 2,
};
enum ELFInstructionSet
{
ELF_INSTRUCTION_SET_NONE = 0,
ELF_INSTRUCTION_SET_X86 = 3,
ELF_INSTRUCTION_SET_ARM = 0x28,
ELF_INSTRUCTION_SET_X64 = 0x3E,
ELF_INSTRUCTION_SET_ARM64 = 0xB7,
ELF_INSTRUCTION_SET_RISCV = 0xF3,
};
enum ELFType
{
ELF_TYPE_RELOCATABLE = 1,
ELF_TYPE_EXECUTABLE = 2,
ELF_TYPE_SHARED = 3,
ELF_TYPE_CORE = 4,
};
typedef struct
{
uint32_t Type;
uint64_t Offset;
uint64_t VirtualAddress;
uint64_t PhysicalAddress;
uint64_t FileSize;
uint64_t MemorySize;
uint32_t Flags;
uint64_t Align;
} ELFProgramHeader;
enum ELFProgramType {
// Program header table entry unused.
ELF_PROGRAM_TYPE_NULL = 0,
// Loadable segment.
ELF_PROGRAM_TYPE_LOAD = 1,
// Dynamic linking information.
ELF_PROGRAM_TYPE_DYNAMIC = 2,
// Interpreter information.
ELF_PROGRAM_TYPE_INTERP = 3,
// Auxiliary information.
ELF_PROGRAM_TYPE_NOTE = 4,
// Reserved
ELF_PROGRAM_TYPE_SHLIB = 5,
// Segment containing program header table itself.
ELF_PROGRAM_TYPE_PHDR = 6,
// Thread-Local Storage template.
ELF_PROGRAM_TYPE_TLS = 7,
// Reserved inclusive range. Operating system specific.
ELF_PROGRAM_TYPE_LOOS = 0x60000000,
ELF_PROGRAM_TYPE_HIOS = 0x6FFFFFFF,
// Reserved inclusive range. Processor specific.
ELF_PROGRAM_TYPE_LOPROC = 0x70000000,
ELF_PROGRAM_TYPE_HIPROC = 0x7FFFFFFF,
};
bool ELF_Read(const char* path, void** entryPoint);
+1398
View File
File diff suppressed because it is too large Load Diff
+220
View File
@@ -0,0 +1,220 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#define EXT2_SUPERBLOCK_OFFSET 1024
#define EXT2_SUPERBLOCK_SIZE 1024
#define EXT2_MAGIC 0xEF53
#define EXT2_NAME_LEN 255
typedef struct ext2_superblock {
unsigned int s_inodes_count; /* Inodes count */
unsigned int s_blocks_count; /* Blocks count */
unsigned int s_r_blocks_count; /* Reserved blocks count */
unsigned int s_free_blocks_count; /* Free blocks count */
unsigned int s_free_inodes_count; /* Free inodes count */
unsigned int s_first_data_block; /* First Data Block */
unsigned int s_log_block_size; /* Block size */
unsigned int s_log_frag_size; /* Fragment size */
unsigned int s_blocks_per_group; /* # Blocks per group */
unsigned int s_frags_per_group; /* # Fragments per group */
unsigned int s_inodes_per_group; /* # Inodes per group */
unsigned int s_mtime; /* Mount time */
unsigned int s_wtime; /* Write time */
unsigned short s_mnt_count; /* Mount count */
unsigned short s_max_mnt_count; /* Maximal mount count */
unsigned short s_magic; /* Magic signature */
unsigned short s_state; /* File system state */
unsigned short s_errors; /* Behaviour when detecting errors */
unsigned short s_minor_rev_level; /* minor revision level */
unsigned int s_lastcheck; /* time of last check */
unsigned int s_checkinterval; /* max. time between checks */
unsigned int s_creator_os; /* OS */
unsigned int s_rev_level; /* Revision level */
unsigned short s_def_resuid; /* Default uid for reserved blocks */
unsigned short s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
unsigned int s_first_ino; /* First non-reserved inode */
unsigned short s_inode_size; /* size of inode structure */
unsigned short s_block_group_nr; /* block group # of this superblock */
unsigned int s_feature_compat; /* compatible feature set */
unsigned int s_feature_incompat; /* incompatible feature set */
unsigned int s_feature_ro_compat; /* readonly-compatible feature set */
unsigned char s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
unsigned int s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
unsigned char s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
unsigned char s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
unsigned short s_padding1;
/*
* Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
*/
unsigned char s_journal_uuid[16]; /* uuid of journal superblock */
unsigned int s_journal_inum; /* inode number of journal file */
unsigned int s_journal_dev; /* device number of journal file */
unsigned int s_last_orphan; /* start of list of inodes to delete */
unsigned int s_hash_seed[4]; /* HTREE hash seed */
unsigned char s_def_hash_version; /* Default hash version to use */
unsigned char s_reserved_char_pad;
unsigned short s_reserved_word_pad;
unsigned int s_default_mount_opts;
unsigned int s_first_meta_bg; /* First metablock block group */
unsigned int s_reserved[190]; /* Padding to the end of the block */
} __attribute__((packed)) ext2_superblock_t;
typedef struct ext2_group_desc {
unsigned int bg_block_bitmap; /* Blocks bitmap block */
unsigned int bg_inode_bitmap; /* Inodes bitmap block */
unsigned int bg_inode_table; /* Inodes table block */
unsigned short bg_free_blocks_count; /* Free blocks count */
unsigned short bg_free_inodes_count; /* Free inodes count */
unsigned short bg_used_dirs_count; /* Directories count */
unsigned short bg_pad;
unsigned int bg_reserved[3];
} __attribute__((packed)) ext2_group_desc_t;
typedef struct ext2_inode {
unsigned short i_mode; /* File mode */
unsigned short i_uid; /* Low 16 bits of Owner Uid */
unsigned int i_size; /* Size in bytes */
unsigned int i_atime; /* Access time */
unsigned int i_ctime; /* Creation time */
unsigned int i_mtime; /* Modification time */
unsigned int i_dtime; /* Deletion Time */
unsigned short i_gid; /* Low 16 bits of Group Id */
unsigned short i_links_count; /* Links count */
unsigned int i_blocks; /* Blocks count IN DISK SECTORS*/
unsigned int i_flags; /* File flags */
unsigned int osd1; /* OS dependent 1 */
unsigned int i_block[15]; /* Pointers to blocks */
unsigned int i_generation; /* File version (for NFS) */
unsigned int i_file_acl; /* File ACL */
unsigned int i_dir_acl; /* Directory ACL */
unsigned int i_faddr; /* Fragment address */
unsigned int extra[3];
} __attribute__((packed)) ext2_inode_t;
typedef struct ext2_dir_entry {
unsigned int inode; /* Inode number */
unsigned short rec_len; /* Directory entry length */
unsigned char name_len; /* Name length */
unsigned char file_type;
char name[]; /* File name, up to EXT2_NAME_LEN */
} __attribute__((packed)) ext2_dir_entry_t;
typedef struct {
uint32_t ino;
uint16_t mode;
uint16_t uid;
uint16_t gid;
uint32_t size;
uint32_t atime;
uint32_t mtime;
uint32_t ctime;
uint32_t nlink;
uint32_t blocks;
} ext2_stat_t;
typedef enum {
EXT2_WRITE_OVERWRITE,
EXT2_WRITE_APPEND,
} ext2_write_mode_t;
// Inode type and permissions
#define EXT2_S_IFIFO 0x1000
#define EXT2_S_IFCHR 0x2000
#define EXT2_S_IFDIR 0x4000
#define EXT2_S_IFBLK 0x6000
#define EXT2_S_IFREG 0x8000
#define EXT2_S_IFLNK 0xA000
#define EXT2_S_IFSOCK 0xC000
#define EXT2_S_IRUSR 0x0100
#define EXT2_S_IWUSR 0x0080
#define EXT2_S_IXUSR 0x0040
#define EXT2_S_IRGRP 0x0020
#define EXT2_S_IWGRP 0x0010
#define EXT2_S_IXGRP 0x0008
#define EXT2_S_IROTH 0x0004
#define EXT2_S_IWOTH 0x0002
#define EXT2_S_IXOTH 0x0001
// File types for directory entries
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
// ── init ──────────────────────────────────────────────────────────────────────
bool ext2_read_superblock(void);
bool ext2_read_group_desc_table(void);
// ── low-level ────────────────────────────────────────────────────────────────
bool ext2_read_block(uint32_t block_num, void* buf);
bool ext2_write_block(uint32_t block_num, const void* buf);
bool ext2_read_inode(uint32_t inode_num, ext2_inode_t* out);
bool ext2_write_inode(uint32_t inode_num, ext2_inode_t* inode);
// ── path / directory ─────────────────────────────────────────────────────────
uint32_t ext2_resolve_path(const char* path); // returns inode num, 0 = not found
bool ext2_find_in_dir(ext2_inode_t* dir, const char* name, uint32_t* out_inum);
bool ext2_read_dir(ext2_inode_t* dir);
bool ext2_read_root_dir(void);
// ── file I/O ─────────────────────────────────────────────────────────────────
bool ext2_read_file(ext2_inode_t* inode, uint8_t* buf);
bool ext2_write_file(ext2_inode_t* inode, uint32_t inode_num,
const uint8_t* data, uint32_t size, ext2_write_mode_t mode);
bool ext2_truncate(ext2_inode_t* inode, uint32_t inode_num, uint32_t new_size);
// ── high-level (operate from a path string) ───────────────────────────────────
bool ext2_read_file_from_root(const char* name, uint8_t* buf, uint32_t* size);
bool ext2_write_file_from_root(const char* name, const uint8_t* data,
uint32_t size, ext2_write_mode_t mode);
// ── create / delete ───────────────────────────────────────────────────────────
bool ext2_create_file(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, uint32_t* out_inum);
bool ext2_mkdir(ext2_inode_t* parent, uint32_t parent_inum,
const char* name, uint32_t* out_inum);
bool ext2_unlink(ext2_inode_t* dir, uint32_t dir_inum, const char* name);
bool ext2_rmdir(ext2_inode_t* parent, uint32_t parent_inum, const char* name);
bool ext2_rename(ext2_inode_t* src_dir, uint32_t src_inum,
ext2_inode_t* dst_dir, uint32_t dst_inum,
const char* old_name, const char* new_name);
// ── symlinks ──────────────────────────────────────────────────────────────────
bool ext2_symlink(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, const char* target);
bool ext2_readlink(uint32_t inode_num, char* buf, uint32_t buf_size);
// ── metadata ─────────────────────────────────────────────────────────────────
bool ext2_stat(uint32_t inode_num, ext2_stat_t* st);
bool ext2_chmod(uint32_t inode_num, uint16_t mode);
bool ext2_chown(uint32_t inode_num, uint16_t uid, uint16_t gid);
const char* ext2_file_type_string(uint8_t type);
+147
View File
@@ -0,0 +1,147 @@
#include "vfs.h"
#include <video/render.h>
#include <arch/x86_64/e9.h>
#include "mp/spinlock.h"
static spinlock_t s_vfs_lock = SPINLOCK_INIT;
static vfs_file_t vfs_fd_table[VFS_MAX_FDS];
fd_t VFS_Open_internal(const char* path)
{
uint32_t ino = ext2_resolve_path(path);
if (ino == 0)
return -1;
// find free fd
for (int i = 4; i < VFS_MAX_FDS; i++)
{
if (!vfs_fd_table[i].used)
{
vfs_fd_table[i].used = true;
vfs_fd_table[i].type = VFS_NODE_EXT2;
vfs_fd_table[i].offset = 0;
vfs_fd_table[i].ext2.inode_num = ino;
if (!ext2_read_inode(ino, &vfs_fd_table[i].ext2.inode))
return -1;
return i;
}
}
return -1;
}
fd_t VFS_Open(const char* path) {
uint64_t flags;
spinlock_acquire_irqsave(&s_vfs_lock, &flags);
fd_t fd = VFS_Open_internal(path);
spinlock_release_irqrestore(&s_vfs_lock, flags);
return fd;
}
int VFS_Close_internal(fd_t fd)
{
if (fd < 0 || fd >= VFS_MAX_FDS)
return -1;
vfs_fd_table[fd].used = false;
return 0;
}
int VFS_Close(fd_t fd) {
uint64_t flags;
spinlock_acquire_irqsave(&s_vfs_lock, &flags);
int resp = VFS_Close_internal(fd);
spinlock_release_irqrestore(&s_vfs_lock, flags);
return resp;
}
int VFS_Read(fd_t fd, uint8_t* buf, size_t size)
{
if (fd < 0 || fd >= VFS_MAX_FDS)
return -1;
vfs_file_t* file = &vfs_fd_table[fd];
if (!file->used)
return -1;
switch (file->type)
{
case VFS_NODE_EXT2:
{
uint32_t file_size = file->ext2.inode.i_size;
if (file->offset >= file_size)
return 0;
// clamp read
if (file->offset + size > file_size)
size = file_size - file->offset;
// naive: read whole file then slice
uint8_t tmp[file_size];
if (!ext2_read_file(&file->ext2.inode, tmp))
return -1;
for (size_t i = 0; i < size; i++)
buf[i] = tmp[file->offset + i];
file->offset += size;
return size;
}
default:
return -1;
}
}
int VFS_Write(fd_t file, uint8_t* data, size_t size)
{
switch (file)
{
case VFS_FD_STDIN:
return 0;
case VFS_FD_STDOUT:
for (size_t i = 0; i < size; i++)
putchar(data[i]);
return size;
case VFS_FD_STDERR:
for (size_t i = 0; i < size; i++)
putchar(data[i]);
return size;
case VFS_FD_DEBUG:
for (size_t i = 0; i < size; i++)
e9_putc(data[i]);
return size;
default:
break;
}
if (file < 0 || file >= VFS_MAX_FDS)
return -1;
vfs_file_t* f = &vfs_fd_table[file];
if (!f->used)
return -1;
if (f->type == VFS_NODE_EXT2)
{
if (!ext2_write_file(
&f->ext2.inode,
f->ext2.inode_num,
data,
size,
EXT2_WRITE_APPEND))
return -1;
return size;
}
return -1;
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "ext2.h"
typedef int fd_t;
#define VFS_MAX_FDS 32
#define VFS_FD_STDIN 0
#define VFS_FD_STDOUT 1
#define VFS_FD_STDERR 2
#define VFS_FD_DEBUG 3
typedef enum {
VFS_NODE_NONE,
VFS_NODE_EXT2,
VFS_NODE_DEVICE
} vfs_node_type_t;
typedef struct {
vfs_node_type_t type;
union {
struct {
uint32_t inode_num;
ext2_inode_t inode;
} ext2;
};
size_t offset;
bool used;
} vfs_file_t;
// API
fd_t VFS_Open(const char* path);
int VFS_Read(fd_t fd, uint8_t* buf, size_t size);
int VFS_Write(fd_t fd, uint8_t* data, size_t size);
int VFS_Close(fd_t fd);
+634
View File
@@ -0,0 +1,634 @@
/* SPDX-License-Identifier: 0BSD */
/* Copyright (C) 2022-2026 Mintsuki and contributors.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef LIMINE_H
#define LIMINE_H 1
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Misc */
#ifdef LIMINE_NO_POINTERS
# define LIMINE_PTR(TYPE) uint64_t
#else
# define LIMINE_PTR(TYPE) TYPE
#endif
#define LIMINE_REQUESTS_START_MARKER { 0xf6b8f4b39de7d1ae, 0xfab91a6940fcb9cf, \
0x785c6ed015d3e316, 0x181e920a7852b9d9 }
#define LIMINE_REQUESTS_END_MARKER { 0xadc0e0531bb10d03, 0x9572709f31764c62 }
#define LIMINE_BASE_REVISION(N) { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N) }
#define LIMINE_BASE_REVISION_SUPPORTED(VAR) ((VAR)[2] == 0)
#define LIMINE_LOADED_BASE_REVISION_VALID(VAR) ((VAR)[1] != 0x6a7b384944536bdc)
#define LIMINE_LOADED_BASE_REVISION(VAR) ((VAR)[1])
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
struct limine_uuid {
uint32_t a;
uint16_t b;
uint16_t c;
uint8_t d[8];
};
#define LIMINE_MEDIA_TYPE_GENERIC 0
#define LIMINE_MEDIA_TYPE_OPTICAL 1
#define LIMINE_MEDIA_TYPE_TFTP 2
struct limine_file {
uint64_t revision;
LIMINE_PTR(void *) address;
uint64_t size;
LIMINE_PTR(char *) path;
LIMINE_PTR(char *) string;
uint32_t media_type;
uint32_t unused;
uint32_t tftp_ip;
uint32_t tftp_port;
uint32_t partition_index;
uint32_t mbr_disk_id;
struct limine_uuid gpt_disk_uuid;
struct limine_uuid gpt_part_uuid;
struct limine_uuid part_uuid;
};
/* Boot info */
#define LIMINE_BOOTLOADER_INFO_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
struct limine_bootloader_info_response {
uint64_t revision;
LIMINE_PTR(char *) name;
LIMINE_PTR(char *) version;
};
struct limine_bootloader_info_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_bootloader_info_response *) response;
};
/* Executable command line */
#define LIMINE_EXECUTABLE_CMDLINE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x4b161536e598651e, 0xb390ad4a2f1f303a }
struct limine_executable_cmdline_response {
uint64_t revision;
LIMINE_PTR(char *) cmdline;
};
struct limine_executable_cmdline_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_executable_cmdline_response *) response;
};
/* Firmware type */
#define LIMINE_FIRMWARE_TYPE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x8c2f75d90bef28a8, 0x7045a4688eac00c3 }
#define LIMINE_FIRMWARE_TYPE_X86BIOS 0
#define LIMINE_FIRMWARE_TYPE_EFI32 1
#define LIMINE_FIRMWARE_TYPE_EFI64 2
#define LIMINE_FIRMWARE_TYPE_SBI 3
struct limine_firmware_type_response {
uint64_t revision;
uint64_t firmware_type;
};
struct limine_firmware_type_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_firmware_type_response *) response;
};
/* Stack size */
#define LIMINE_STACK_SIZE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d }
struct limine_stack_size_response {
uint64_t revision;
};
struct limine_stack_size_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_stack_size_response *) response;
uint64_t stack_size;
};
/* HHDM */
#define LIMINE_HHDM_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b }
struct limine_hhdm_response {
uint64_t revision;
uint64_t offset;
};
struct limine_hhdm_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_hhdm_response *) response;
};
/* Framebuffer */
#define LIMINE_FRAMEBUFFER_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b }
#define LIMINE_FRAMEBUFFER_RGB 1
struct limine_video_mode {
uint64_t pitch;
uint64_t width;
uint64_t height;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
};
struct limine_framebuffer {
LIMINE_PTR(void *) address;
uint64_t width;
uint64_t height;
uint64_t pitch;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
uint8_t unused[7];
uint64_t edid_size;
LIMINE_PTR(void *) edid;
/* Response revision 1 */
uint64_t mode_count;
LIMINE_PTR(struct limine_video_mode **) modes;
};
struct limine_framebuffer_response {
uint64_t revision;
uint64_t framebuffer_count;
LIMINE_PTR(struct limine_framebuffer **) framebuffers;
};
struct limine_framebuffer_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_framebuffer_response *) response;
};
/* Flanterm FB init params */
#define LIMINE_FLANTERM_FB_INIT_PARAMS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3259399fe7c5f126, 0xe01c1c8c5db9d1a9 }
#define LIMINE_FLANTERM_FB_ROTATE_0 0
#define LIMINE_FLANTERM_FB_ROTATE_90 1
#define LIMINE_FLANTERM_FB_ROTATE_180 2
#define LIMINE_FLANTERM_FB_ROTATE_270 3
struct limine_flanterm_fb_init_params {
LIMINE_PTR(uint32_t *) canvas;
uint64_t canvas_size;
uint32_t ansi_colours[8];
uint32_t ansi_bright_colours[8];
uint32_t default_bg;
uint32_t default_fg;
uint32_t default_bg_bright;
uint32_t default_fg_bright;
LIMINE_PTR(void *) font;
uint64_t font_width;
uint64_t font_height;
uint64_t font_spacing;
uint64_t font_scale_x;
uint64_t font_scale_y;
uint64_t margin;
uint64_t rotation;
};
struct limine_flanterm_fb_init_params_response {
uint64_t revision;
uint64_t entry_count;
LIMINE_PTR(struct limine_flanterm_fb_init_params **) entries;
};
struct limine_flanterm_fb_init_params_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_flanterm_fb_init_params_response *) response;
};
/* Paging mode */
#define LIMINE_PAGING_MODE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
#define LIMINE_PAGING_MODE_X86_64_MIN LIMINE_PAGING_MODE_X86_64_4LVL
#define LIMINE_PAGING_MODE_X86_64_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
#define LIMINE_PAGING_MODE_AARCH64_MIN LIMINE_PAGING_MODE_AARCH64_4LVL
#define LIMINE_PAGING_MODE_AARCH64_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
#define LIMINE_PAGING_MODE_RISCV_SV39 0
#define LIMINE_PAGING_MODE_RISCV_SV48 1
#define LIMINE_PAGING_MODE_RISCV_SV57 2
#define LIMINE_PAGING_MODE_RISCV_MIN LIMINE_PAGING_MODE_RISCV_SV39
#define LIMINE_PAGING_MODE_RISCV_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
#define LIMINE_PAGING_MODE_LOONGARCH_4LVL 0
#define LIMINE_PAGING_MODE_LOONGARCH_MIN LIMINE_PAGING_MODE_LOONGARCH_4LVL
#define LIMINE_PAGING_MODE_LOONGARCH_DEFAULT LIMINE_PAGING_MODE_LOONGARCH_4LVL
struct limine_paging_mode_response {
uint64_t revision;
uint64_t mode;
};
struct limine_paging_mode_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_paging_mode_response *) response;
uint64_t mode;
uint64_t max_mode;
uint64_t min_mode;
};
/* MP */
#define LIMINE_MP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 }
struct limine_mp_info;
typedef void (*limine_goto_address)(struct limine_mp_info *);
#if defined (__x86_64__) || defined (__i386__)
#define LIMINE_MP_RESPONSE_X86_64_X2APIC (1 << 0)
struct limine_mp_info {
uint32_t processor_id;
uint32_t lapic_id;
uint64_t reserved;
LIMINE_PTR(limine_goto_address) goto_address;
uint64_t extra_argument;
};
struct limine_mp_response {
uint64_t revision;
uint32_t flags;
uint32_t bsp_lapic_id;
uint64_t cpu_count;
LIMINE_PTR(struct limine_mp_info **) cpus;
};
#elif defined (__aarch64__)
struct limine_mp_info {
uint32_t processor_id;
uint32_t reserved1;
uint64_t mpidr;
uint64_t reserved;
LIMINE_PTR(limine_goto_address) goto_address;
uint64_t extra_argument;
};
struct limine_mp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_mpidr;
uint64_t cpu_count;
LIMINE_PTR(struct limine_mp_info **) cpus;
};
#elif defined (__riscv) && (__riscv_xlen == 64)
struct limine_mp_info {
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
LIMINE_PTR(limine_goto_address) goto_address;
uint64_t extra_argument;
};
struct limine_mp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
LIMINE_PTR(struct limine_mp_info **) cpus;
};
#elif defined (__loongarch__) && (__loongarch_grlen == 64)
struct limine_mp_info {
uint64_t processor_id;
uint64_t phys_id;
uint64_t reserved;
LIMINE_PTR(limine_goto_address) goto_address;
uint64_t extra_argument;
};
struct limine_mp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_phys_id;
uint64_t cpu_count;
LIMINE_PTR(struct limine_mp_info **) cpus;
};
#else
#error Unknown architecture
#endif
#define LIMINE_MP_REQUEST_X86_64_X2APIC (1 << 0)
struct limine_mp_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_mp_response *) response;
uint64_t flags;
};
/* Memory map */
#define LIMINE_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 }
#define LIMINE_MEMMAP_USABLE 0
#define LIMINE_MEMMAP_RESERVED 1
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
#define LIMINE_MEMMAP_ACPI_NVS 3
#define LIMINE_MEMMAP_BAD_MEMORY 4
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
#define LIMINE_MEMMAP_EXECUTABLE_AND_MODULES 6
#define LIMINE_MEMMAP_FRAMEBUFFER 7
#define LIMINE_MEMMAP_RESERVED_MAPPED 8
struct limine_memmap_entry {
uint64_t base;
uint64_t length;
uint64_t type;
};
struct limine_memmap_response {
uint64_t revision;
uint64_t entry_count;
LIMINE_PTR(struct limine_memmap_entry **) entries;
};
struct limine_memmap_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_memmap_response *) response;
};
/* Entry point */
#define LIMINE_ENTRY_POINT_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
typedef void (*limine_entry_point)(void);
struct limine_entry_point_response {
uint64_t revision;
};
struct limine_entry_point_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_entry_point_response *) response;
LIMINE_PTR(limine_entry_point) entry;
};
/* Executable File */
#define LIMINE_EXECUTABLE_FILE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 }
struct limine_executable_file_response {
uint64_t revision;
LIMINE_PTR(struct limine_file *) executable_file;
};
struct limine_executable_file_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_executable_file_response *) response;
};
/* Module */
#define LIMINE_MODULE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
#define LIMINE_INTERNAL_MODULE_COMPRESSED (1 << 1)
struct limine_internal_module {
LIMINE_PTR(const char *) path;
LIMINE_PTR(const char *) string;
uint64_t flags;
};
struct limine_module_response {
uint64_t revision;
uint64_t module_count;
LIMINE_PTR(struct limine_file **) modules;
};
struct limine_module_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_module_response *) response;
/* Request revision 1 */
uint64_t internal_module_count;
LIMINE_PTR(struct limine_internal_module **) internal_modules;
};
/* RSDP */
#define LIMINE_RSDP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c }
struct limine_rsdp_response {
uint64_t revision;
LIMINE_PTR(void *) address;
};
struct limine_rsdp_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_rsdp_response *) response;
};
/* SMBIOS */
#define LIMINE_SMBIOS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee }
struct limine_smbios_response {
uint64_t revision;
LIMINE_PTR(void *) entry_32;
LIMINE_PTR(void *) entry_64;
};
struct limine_smbios_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_smbios_response *) response;
};
/* EFI system table */
#define LIMINE_EFI_SYSTEM_TABLE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc }
struct limine_efi_system_table_response {
uint64_t revision;
LIMINE_PTR(void *) address;
};
struct limine_efi_system_table_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_efi_system_table_response *) response;
};
/* EFI memory map */
#define LIMINE_EFI_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x7df62a431d6872d5, 0xa4fcdfb3e57306c8 }
struct limine_efi_memmap_response {
uint64_t revision;
LIMINE_PTR(void *) memmap;
uint64_t memmap_size;
uint64_t desc_size;
uint64_t desc_version;
};
struct limine_efi_memmap_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_efi_memmap_response *) response;
};
/* Date at boot */
#define LIMINE_DATE_AT_BOOT_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 }
struct limine_date_at_boot_response {
uint64_t revision;
int64_t timestamp;
};
struct limine_date_at_boot_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_date_at_boot_response *) response;
};
/* Executable address */
#define LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 }
struct limine_executable_address_response {
uint64_t revision;
uint64_t physical_base;
uint64_t virtual_base;
};
struct limine_executable_address_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_executable_address_response *) response;
};
/* Device Tree Blob */
#define LIMINE_DTB_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7 }
struct limine_dtb_response {
uint64_t revision;
LIMINE_PTR(void *) dtb_ptr;
};
struct limine_dtb_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_dtb_response *) response;
};
/* RISC-V Boot Hart ID */
#define LIMINE_RISCV_BSP_HARTID_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x1369359f025525f9, 0x2ff2a56178391bb6 }
struct limine_riscv_bsp_hartid_response {
uint64_t revision;
uint64_t bsp_hartid;
};
struct limine_riscv_bsp_hartid_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_riscv_bsp_hartid_response *) response;
};
/* Bootloader Performance */
#define LIMINE_BOOTLOADER_PERFORMANCE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x6b50ad9bf36d13ad, 0xdc4c7e88fc759e17 }
struct limine_bootloader_performance_response {
uint64_t revision;
uint64_t reset_usec;
uint64_t init_usec;
uint64_t exec_usec;
};
struct limine_bootloader_performance_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_bootloader_performance_response *) response;
};
#define LIMINE_KEEP_IOMMU_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x8ebaabe51f490179, 0x2aa86a59ffb4ab0f }
struct limine_keep_iommu_response {
uint64_t revision;
};
struct limine_keep_iommu_request {
uint64_t id[4];
uint64_t revision;
LIMINE_PTR(struct limine_keep_iommu_response *) response;
};
#ifdef __cplusplus
}
#endif
#endif
+335
View File
@@ -0,0 +1,335 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <limine.h>
#include "video/render.h"
#include "video/tga.h"
#include "stdio.h"
#include "arch/x86_64/gdt.h"
#include "arch/x86_64/idt.h"
#include "arch/x86_64/isr.h"
#include "arch/x86_64/irq.h"
#include "mm/memory.h"
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "arch/x86_64/ata.h"
#include "fs/ext2.h"
#include "string.h"
#include "arch/x86_64/io.h"
#include "arch/x86_64/usermode.h"
#include "syscall/syscall.h"
#include "fs/vfs.h"
uintptr_t g_hhdm_offset;
#define CPU_STACK_SIZE (64 * 1024)
// Set the base revision to 6, this is recommended as this is the latest
// base revision described by the Limine boot protocol specification.
// See specification for further info.
__attribute__((used, section(".limine_requests")))
static volatile uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(6);
// The Limine requests can be placed anywhere, but it is important that
// the compiler does not optimise them away, so, usually, they should
// be made volatile or equivalent, _and_ they should be accessed at least
// once or marked as used with the "used" attribute as done here.
__attribute__((used, section(".limine_requests")))
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST_ID,
.revision = 6
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST_ID,
.revision = 6
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_stack_size_request stack_size_request = {
.id = LIMINE_STACK_SIZE_REQUEST_ID,
.revision = 0,
.stack_size = CPU_STACK_SIZE,
};
// Finally, define the start and end markers for the Limine requests.
// These can also be moved anywhere, to any .c file, as seen fit.
__attribute__((used, section(".limine_requests_start")))
static volatile uint64_t limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end")))
static volatile uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
// GCC and Clang reserve the right to generate calls to the following
// 4 functions even if they are not directly called.
// Implement them as the C specification mandates.
// DO NOT remove or rename these functions, or stuff will eventually break!
// They CAN be moved to a different .c file.
// Halt and catch fire function.
static void hcf(void) {
for (;;) {
asm volatile ("pause");
}
}
// The following will be our kernel's entry point.
// If renaming kmain() to something else, make sure to change the
// linker script accordingly.
void kmain(void) {
// Ensure the bootloader actually understands our base revision (see spec).
if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
hcf();
}
// Ensure we got a framebuffer.
if (framebuffer_request.response == NULL
|| framebuffer_request.response->framebuffer_count < 1) {
hcf();
}
// Fetch the first framebuffer.
struct limine_framebuffer *framebuffer = framebuffer_request.response->framebuffers[0];
struct limine_memmap_response *memmap_response = memmap_request.response;
if (!memmap_response) {
hcf();
}
fb = framebuffer->address;
fb_width = framebuffer->width;
fb_height = framebuffer->height;
fb_pitch = framebuffer->pitch / 4;
printf("Hello, Kernel!\n");
printf("Number: %d\n", 1234);
printf("Hex: %x\n", 0xBEEF);
for (size_t i = 0; i < memmap_response->entry_count; i++) {
struct limine_memmap_entry *entry = memmap_response->entries[i];
printf("Base: 0x%x%x, Length: 0x%x%x, Type: %d\n",
(uint32_t)(entry->base >> 32), (uint32_t)entry->base,
(uint32_t)(entry->length >> 32), (uint32_t)entry->length,
entry->type);
}
x86_64_DisableInterrupts();
/*uint32_t msr_lo, msr_hi;
asm volatile("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(0x1B));
msr_lo &= ~(1 << 11);
asm volatile("wrmsr" : : "a"(msr_lo), "d"(msr_hi), "c"(0x1B));*/
printf("init pmm");
pmm_init(memmap_response->entries, memmap_response->entry_count);
printf("init slab");
slab_init();
printf("init vmm");
vmm_init(memmap_response->entries, memmap_response->entry_count);
printf("init gdt");
x86_64_GDT_Initialize();
x86_64_IDT_Initialize();
x86_64_ISR_Initialize();
x86_64_IRQ_Initialize();
x86_64_EnableInterrupts();
//lapic_timer_start(100);
ata_init();
ata_identify();
if (!ext2_read_superblock()) {
printf("EXT2 failed\n");
hcf();
}
if (!ext2_read_group_desc_table()) {
printf("GDT failed\n");
hcf();
}
ext2_read_root_dir();
printf("test");
uint8_t* file_buffer = kmalloc(4096); // adjust if needed
uint32_t file_size = 0;
if (ext2_read_file_from_root("a.txt", file_buffer, &file_size)) {
printf("Read file (size %d):\n", file_size);
for (uint32_t i = 0; i < file_size; i++) {
printf("%c", file_buffer[i]); // or printf("%c", ...)
}
printf("\n");
} else {
printf("Failed to read file\n");
}
kfree(file_buffer);
uint8_t* file2_buffer = kmalloc(4096); // adjust if needed
uint32_t file2_size = 0;
if (ext2_read_file_from_root("dogcatman.txt", file2_buffer, &file2_size)) {
printf("Read file (size %d):\n", file2_size);
for (uint32_t i = 0; i < file2_size; i++) {
printf("%c", file2_buffer[i]); // or printf("%c", ...)
}
printf("\n");
} else {
printf("Failed to read file\n");
}
kfree(file2_buffer);
uint8_t* file3_buffer = kmalloc(4096); // adjust if needed
uint32_t file3_size = 0;
if (ext2_read_file_from_root("test.txt", file3_buffer, &file3_size)) {
printf("Read file (size %d):\n", file3_size);
for (uint32_t i = 0; i < file3_size; i++) {
printf("%c", file3_buffer[i]); // or printf("%c", ...)
}
printf("\n");
} else {
printf("Failed to read file\n");
}
kfree(file3_buffer);
uint8_t* file4_buffer = kmalloc(4096); // adjust if needed
uint32_t file4_size = 0;
if (ext2_read_file_from_root("qwerty.txt", file4_buffer, &file4_size)) {
printf("Read file (size %d):\n", file4_size);
for (uint32_t i = 0; i < file4_size; i++) {
printf("%c", file4_buffer[i]); // or printf("%c", ...)
}
printf("\n");
} else {
printf("Failed to read file\n");
}
kfree(file4_buffer);
const char* msg = "hello i wrote from kernel!";
ext2_write_file_from_root("qwerty.txt", (const uint8_t*)msg, strlen(msg), EXT2_WRITE_APPEND);
uint8_t* file5_buffer = kmalloc(4096); // adjust if needed
uint32_t file5_size = 0;
if (ext2_read_file_from_root("qwerty.txt", file5_buffer, &file5_size)) {
printf("Read file (size %d):\n", file5_size);
for (uint32_t i = 0; i < file5_size; i++) {
printf("%c", file5_buffer[i]); // or printf("%c", ...)
}
printf("\n");
} else {
printf("Failed to read file\n");
}
kfree(file5_buffer);
uint32_t inum = ext2_resolve_path("charlie.tga");
if (!inum) {
printf("file not found\n");
hcf();
}
ext2_inode_t inode;
if (!ext2_read_inode(inum, &inode)) {
printf("inode read failed\n");
hcf();
}
uint32_t tga_size = inode.i_size;
if (!tga_size) {
printf("tga file is empty\n");
hcf();
}
uint8_t *file_buf = kmalloc(tga_size);
if (!file_buf) {
printf("OOM allocating tga buffer (%u bytes)\n", tga_size);
hcf();
}
if (!ext2_read_file(&inode, file_buf)) {
printf("read failed\n");
kfree(file_buf);
hcf();
}
uint32_t *img = tga_parse(file_buf, tga_size);
kfree(file_buf); // free the raw file buffer as soon as parse is done
if (!img) {
printf("tga parse failed\n");
hcf();
}
int x = 0;
int y = 0;
int new_w = img[0] * 5;
int new_h = img[1] * 5;
clear_screen(0xFF1E1E1E);
draw_image_bilinear(img, x, y, new_w, new_h);
kfree(img);
//clear_screen(0xFF1E1E1E);
fd_t fd = VFS_Open("/a.txt");
if (fd < 0) {
printf("asudg");
}
uint8_t buf[128];
int n;
while ((n = VFS_Read(fd, buf, sizeof(buf))) > 0)
{
VFS_Write(VFS_FD_STDOUT, buf, n);
}
VFS_Close(fd);
x86_64_EnableInterrupts();
syscall_init();
start_userspace();
printf("tst");
// We're done, just hang...
hcf();
}
+68
View File
@@ -0,0 +1,68 @@
#include <stdint.h>
#include "stddef.h"
#include "pmm.h"
#include "stdio.h"
#include "vmm.h"
#include <stdbool.h>
#include "mp/spinlock.h"
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
uint8_t *restrict pdest = (uint8_t *restrict)dest;
const uint8_t *restrict psrc = (const uint8_t *restrict)src;
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
return dest;
}
void *memset(void *s, int c, size_t n) {
uint8_t *p = (uint8_t *)s;
for (size_t i = 0; i < n; i++) {
p[i] = (uint8_t)c;
}
return s;
}
void *memmove(void *dest, const void *src, size_t n) {
uint8_t *pdest = (uint8_t *)dest;
const uint8_t *psrc = (const uint8_t *)src;
if ((uintptr_t)src > (uintptr_t)dest) {
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
} else if ((uintptr_t)src < (uintptr_t)dest) {
for (size_t i = n; i > 0; i--) {
pdest[i-1] = psrc[i-1];
}
}
return dest;
}
int memcmp(const void *s1, const void *s2, size_t n) {
const uint8_t *p1 = (const uint8_t *)s1;
const uint8_t *p2 = (const uint8_t *)s2;
for (size_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) {
return p1[i] < p2[i] ? -1 : 1;
}
}
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include "stddef.h"
#include "slab.h" // kmalloc/kfree now come from slab
#define ALIGN_DOWN(x, a) ((x) & ~((a)-1))
#define ALIGN_UP(x, a) (((x) + (a)-1) & ~((a)-1))
#define SIZEOF_ARRAY(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
#define DIV_ROUNDUP(A, B) \
({ \
__auto_type _a_ = A; \
__auto_type _b_ = B; \
(_a_ + (_b_ - 1)) / _b_; \
})
void *memcpy(void *restrict dest, const void *restrict src, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
void *memmove(void *dest, const void *src, size_t n);
#define memzero(a, b) memset(a, 0, b)
#define kmalloc slab_alloc
#define kfree slab_free
#define krealloc slab_realloc
+123
View File
@@ -0,0 +1,123 @@
#include "pmm.h"
#include "vmm.h" // for MEM_PHYS_OFFSET
#include "memory.h" // memset
#include "stdio.h"
static spinlock_t memory_lock = SPINLOCK_INIT;
static uint8_t *bitmap = NULL;
static uint64_t total_page_count = 0;
static uint64_t last_used_index = 0;
static uint64_t free_pages = 0;
void pmm_init(struct limine_memmap_entry **memmap, size_t memmapentries) {
uint64_t highest_addr = 0;
size_t memmap_entries = memmapentries - 1;
for (size_t i = 0; i < memmap_entries; i++) {
if (memmap[i]->type != LIMINE_MEMMAP_USABLE &&
memmap[i]->type != LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE)
continue;
uint64_t top = memmap[i]->base + memmap[i]->length;
if (top > highest_addr) highest_addr = top;
}
total_page_count = highest_addr / PAGE_SIZE;
size_t bitmap_size = ALIGN_UP(total_page_count / 8, PAGE_SIZE);
printf("MEM_PHYS_OFFSET: %x\n", MEM_PHYS_OFFSET);
printf("memmap_entries: %u\n", memmap_entries);
// Find place for bitmap
for (size_t i = 0; i < memmap_entries; i++) {
printf("i: %u\n", i);
if (memmap[i]->type != LIMINE_MEMMAP_USABLE) continue;
if (memmap[i]->length >= bitmap_size) {
printf("test\n");
bitmap = (uint8_t *)(memmap[i]->base + MEM_PHYS_OFFSET);
printf("bitmap: %x\n", bitmap);
printf("bitmap_size: %x\n", bitmap_size);
memset(bitmap, 0xFF, bitmap_size);
printf("test3\n");
printf("memmap base: %x\n", memmap[i]->base);
printf("memmap length: %x\n", memmap[i]->length);
memmap[i]->base += bitmap_size;
memmap[i]->length -= bitmap_size;
printf("test4\n");
printf("memmap[7]->type: %u\n", memmap[7]->type);
printf("memmap[8]->type: %u\n", memmap[8]->type);
printf("memmap[9]->type: %u\n", memmap[9]->type);
printf("memmap[10]->type: %u\n", memmap[10]->type); //#define LIMINE_MEMMAP_USABLE 0
printf("memmap[11]->type: %u\n", memmap[11]->type); //#define LIMINE_MEMMAP_RESERVED 1
printf("memmap[12]->type: %u\n", memmap[12]->type); //#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
printf("memmap[13]->type: %u\n", memmap[13]->type); //#define LIMINE_MEMMAP_ACPI_NVS 3
printf("memmap[14]->type: %u\n", memmap[14]->type); //#define LIMINE_MEMMAP_BAD_MEMORY 4
printf("memmap[15]->type: %u\n", memmap[15]->type); //#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
printf("memmap[16]->type: %u\n", memmap[16]->type); //#define LIMINE_MEMMAP_EXECUTABLE_AND_MODULES 6
printf("memmap[17]->type: %u\n", memmap[17]->type); //#define LIMINE_MEMMAP_FRAMEBUFFER 7
//printf("memmap[18]->type: %u\n", memmap[18]->type); //#define LIMINE_MEMMAP_RESERVED_MAPPED 8, commented out because it triple faults for some reason
break;
}
}
printf("break");
// Mark usable pages free
for (size_t i = 0; i < memmap_entries; i++) {
if (memmap[i]->type != LIMINE_MEMMAP_USABLE) continue;
for (uint64_t j = 0; j < memmap[i]->length; j += PAGE_SIZE) {
size_t bit = (memmap[i]->base + j) / PAGE_SIZE;
bitmap[bit / 8] &= ~(1u << (bit % 8));
free_pages++;
}
}
printf("done");
}
static void *inner_alloc(size_t pages, size_t limit) {
size_t p = 0;
while (last_used_index < limit) {
if (!(bitmap[last_used_index / 8] & (1u << (last_used_index % 8)))) {
if (++p == pages) {
size_t page = last_used_index - pages + 1;
for (size_t i = page; i < page + pages; i++)
bitmap[i / 8] |= (1u << (i % 8));
last_used_index = page + pages;
return (void *)(page * PAGE_SIZE);
}
} else {
p = 0;
}
last_used_index++;
}
return NULL;
}
void *pmm_alloc(size_t pages) {
spinlock_acquire_or_wait(&memory_lock);
size_t last = last_used_index;
void *ret = inner_alloc(pages, total_page_count);
if (!ret) {
last_used_index = 0;
ret = inner_alloc(pages, last);
}
if (ret) free_pages -= pages;
spinlock_drop(&memory_lock);
return ret;
}
void *pmm_allocz(size_t pages) {
void *ret = pmm_alloc(pages);
if (ret) {
memset((void *)((uintptr_t)ret + MEM_PHYS_OFFSET), 0, pages * PAGE_SIZE); // this is at fault for the page fault
}
return ret;
}
void pmm_free(void *addr, size_t pages) {
spinlock_acquire_or_wait(&memory_lock);
size_t page = (uintptr_t)addr / PAGE_SIZE;
for (size_t i = 0; i < pages; i++)
bitmap[(page + i) / 8] &= ~(1u << ((page + i) % 8));
free_pages += pages;
spinlock_drop(&memory_lock);
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <limine.h>
void pmm_init(struct limine_memmap_entry **memmap, size_t memmap_entries);
void *pmm_alloc(size_t pages);
void *pmm_allocz(size_t pages);
void pmm_free(void *addr, size_t pages);
+189
View File
@@ -0,0 +1,189 @@
#include "memory.h"
#include <mp/spinlock.h>
#include <mm/pmm.h>
#include <mm/slab.h>
#include <mm/vmm.h>
#include <stdbool.h>
#include <stdint.h>
#include "stdio.h"
struct slab {
spinlock_t lock;
void **first_free;
size_t ent_size;
};
struct slab_header {
struct slab *slab;
};
struct alloc_metadata {
size_t pages;
size_t size;
};
static struct slab slabs[10] = {0};
static inline struct slab *slab_for(size_t size) {
for (size_t i = 0; i < SIZEOF_ARRAY(slabs); i++) {
struct slab *slab = &slabs[i];
if (slab->ent_size >= size) {
return slab;
}
}
return NULL;
}
static void create_slab(struct slab *slab, size_t ent_size) {
spinlock_init(&slab->lock);
slab->first_free = (void **)((uint64_t)pmm_alloc(1) + MEM_PHYS_OFFSET);
slab->ent_size = ent_size;
size_t header_offset = ALIGN_UP(sizeof(struct slab_header), ent_size);
size_t available_size = PAGE_SIZE - header_offset;
struct slab_header *slab_ptr = (struct slab_header *)slab->first_free;
slab_ptr->slab = slab;
slab->first_free = (void **)((void *)slab->first_free + header_offset);
void **arr = (void **)slab->first_free;
size_t max = available_size / ent_size - 1;
size_t fact = ent_size / sizeof(void *);
for (size_t i = 0; i < max; i++) {
arr[i * fact] = &arr[(i + 1) * fact];
}
arr[max * fact] = NULL;
}
static void *alloc_from_slab(struct slab *slab) {
spinlock_acquire_or_wait(&slab->lock);
if (slab->first_free == NULL) {
create_slab(slab, slab->ent_size);
}
void **old_free = slab->first_free;
slab->first_free = *old_free;
memset(old_free, 0, slab->ent_size);
spinlock_drop(&slab->lock);
return old_free;
}
static void free_in_slab(struct slab *slab, void *addr) {
spinlock_acquire_or_wait(&slab->lock);
if (addr == NULL) {
goto cleanup;
}
void **new_head = addr;
*new_head = slab->first_free;
slab->first_free = new_head;
cleanup:
spinlock_drop(&slab->lock);
}
void slab_init(void) {
memzero(slabs, sizeof(struct slab) * 10);
create_slab(&slabs[0], 8);
create_slab(&slabs[1], 16);
create_slab(&slabs[2], 24);
create_slab(&slabs[3], 32);
create_slab(&slabs[4], 48);
create_slab(&slabs[5], 64);
create_slab(&slabs[6], 128);
create_slab(&slabs[7], 256);
create_slab(&slabs[8], 512);
create_slab(&slabs[9], 1024);
}
void *slab_alloc(size_t size) {
struct slab *slab = slab_for(size);
if (slab != NULL) {
return alloc_from_slab(slab);
}
size_t page_count = DIV_ROUNDUP(size, PAGE_SIZE);
uint64_t ret = (uint64_t)pmm_allocz(page_count + 1);
if ((void *)ret == NULL) {
return NULL;
}
ret += MEM_PHYS_OFFSET;
struct alloc_metadata *metadata = (struct alloc_metadata *)ret;
metadata->pages = page_count;
metadata->size = size;
return (void *)(ret + PAGE_SIZE);
}
void *slab_realloc(void *addr, size_t new_size) {
if (addr == NULL) {
return slab_alloc(new_size);
}
if (((uintptr_t)addr & 0xfff) == 0) {
struct alloc_metadata *metadata =
(struct alloc_metadata *)(addr - PAGE_SIZE);
if (DIV_ROUNDUP(metadata->size, PAGE_SIZE) ==
DIV_ROUNDUP(new_size, PAGE_SIZE)) {
metadata->size = new_size;
return addr;
}
void *new_addr = slab_alloc(new_size);
if (new_addr == NULL) {
return NULL;
}
if (metadata->size > new_size) {
memcpy(new_addr, addr, new_size);
} else {
memcpy(new_addr, addr, metadata->size);
}
slab_free(addr);
return new_addr;
}
struct slab_header *slab_header =
(struct slab_header *)((uintptr_t)addr & ~0xfff);
struct slab *slab = slab_header->slab;
if (new_size > slab->ent_size) {
void *new_addr = slab_alloc(new_size);
if (new_addr == NULL) {
return NULL;
}
memcpy(new_addr, addr, slab->ent_size);
free_in_slab(slab, addr);
return new_addr;
}
return addr;
}
void slab_free(void *addr) {
if (addr == NULL) {
return;
}
if (((uintptr_t)addr & 0xfff) == 0) {
struct alloc_metadata *metadata =
(struct alloc_metadata *)(addr - PAGE_SIZE);
pmm_free((void *)((uintptr_t)metadata - MEM_PHYS_OFFSET),
metadata->pages + 1);
return;
}
struct slab_header *slab_header =
(struct slab_header *)((uintptr_t)addr & ~0xfff);
free_in_slab(slab_header->slab, addr);
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef SLAB_H
#define SLAB_H
#include <stddef.h>
void slab_init(void);
void *slab_alloc(size_t size);
void *slab_realloc(void *addr, size_t size);
void slab_free(void *addr);
static inline void *kmalloc(size_t size) {
return slab_alloc(size);
}
static inline void *krealloc(void *addr, size_t size) {
return slab_realloc(addr, size);
}
static inline void kfree(void *addr) {
return slab_free(addr);
}
#define kcalloc(A, B) kmalloc(A * sizeof(B))
#endif
+295
View File
@@ -0,0 +1,295 @@
#include "vmm.h"
#include "pmm.h"
#include "memory.h"
#include "stdio.h"
struct pagemap *kernel_pagemap = NULL;
__attribute__((used, section(".limine_requests")))
volatile struct limine_hhdm_request hhdm_request = {
.id = LIMINE_HHDM_REQUEST_ID, .revision = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_executable_address_request kernel_address_request = {
.id = LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID, .revision = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_paging_mode_request paging_mode_request = {
.id = LIMINE_PAGING_MODE_REQUEST_ID, .revision = 0, .mode = LIMINE_PAGING_MODE_X86_64_4LVL
};
static uint64_t *get_next_level(uint64_t *top_level, size_t idx, bool allocate) {
if (top_level[idx] & 1)
return (uint64_t *)((top_level[idx] & ~0xFFFULL) + MEM_PHYS_OFFSET);
if (!allocate) return NULL;
void *next = pmm_allocz(1);
if (!next) return NULL;
top_level[idx] = (uint64_t)next | 0b111;
return (uint64_t *)((uintptr_t)next + MEM_PHYS_OFFSET);
}
void vmm_init(struct limine_memmap_entry **memmap, size_t memmapentries) {
if (!hhdm_request.response) {
printf("PRAISE BE TO LIMINE WE DON'T HAE HHDM RESP");
}
size_t memmap_entries = memmapentries - 1;
kernel_pagemap = kmalloc(sizeof(struct pagemap));
if (!kernel_pagemap) {
printf("VMM: OOm allocating kernel_pagemap\n");
while(1) asm volatile ("hlt");
}
spinlock_init(&kernel_pagemap->lock);
kernel_pagemap->top_level = (uint64_t *)((uintptr_t)pmm_allocz(1) + MEM_PHYS_OFFSET);
if (!kernel_pagemap->top_level) {
printf("VMM: OOM allocating PML4\n");
while (1) asm volatile ("hlt");
}
// Identity map lower half + HHDM
for (uint64_t p = 256; p < 512; p++)
get_next_level(kernel_pagemap->top_level, p, true);
// Map all physical memory (HHDM)
for (uint64_t p = 0; p < 0x8000000000ULL; p += 0x200000) // 2 MiB pages up to 256 GiB
vmm_map_page(kernel_pagemap, p + MEM_PHYS_OFFSET, p, PAGE_READ | PAGE_WRITE, Size2MiB);
// Map kernel sections with correct permissions
extern char __text_start_addr[], __text_end_addr[];
extern char __rodata_start_addr[], __rodata_end_addr[];
extern char __data_start_addr[], __data_end_addr[];
extern char __bss_start_addr[], __bss_end_addr[];
uintptr_t text_start = ALIGN_DOWN((uintptr_t)__text_start_addr, PAGE_SIZE);
uintptr_t text_end = ALIGN_UP((uintptr_t)__text_end_addr, PAGE_SIZE);
uintptr_t rodata_start = ALIGN_DOWN((uintptr_t)__rodata_start_addr, PAGE_SIZE);
uintptr_t rodata_end = ALIGN_UP((uintptr_t)__rodata_end_addr, PAGE_SIZE);
uintptr_t data_start = ALIGN_DOWN((uintptr_t)__data_start_addr, PAGE_SIZE);
uintptr_t data_end = ALIGN_UP((uintptr_t)__data_end_addr, PAGE_SIZE);
uintptr_t bss_start = ALIGN_DOWN((uintptr_t)__bss_start_addr, PAGE_SIZE);
uintptr_t bss_end = ALIGN_UP((uintptr_t)__bss_end_addr, PAGE_SIZE);
uint64_t paddr = kernel_address_request.response->physical_base;
uint64_t vaddr = kernel_address_request.response->virtual_base;
// Map everything from kernel load address up to .text (this is the requests section)
for (uintptr_t va = vaddr; va < text_start; va += PAGE_SIZE) {
uint64_t pa = va - vaddr + paddr;
vmm_map_page(kernel_pagemap, va, pa,
PAGE_READ | PAGE_WRITE | PAGE_NO_EXECUTE, Size4KiB);
}
for (uintptr_t va = text_start; va < text_end; va += PAGE_SIZE) {
uint64_t pa = va - vaddr + paddr;
vmm_map_page(kernel_pagemap, va, pa, PAGE_READ, Size4KiB);
}
// .rodata : R-- + NX
for (uintptr_t va = rodata_start; va < rodata_end; va += PAGE_SIZE) {
uint64_t pa = va - vaddr + paddr;
vmm_map_page(kernel_pagemap, va, pa, PAGE_READ | PAGE_NO_EXECUTE, Size4KiB);
}
// .data : RW- + NX
for (uintptr_t va = data_start; va < data_end; va += PAGE_SIZE) {
uint64_t pa = va - vaddr + paddr;
vmm_map_page(kernel_pagemap, va, pa, PAGE_READ | PAGE_WRITE | PAGE_NO_EXECUTE, Size4KiB);
}
// .bss : RW- + NX (stack lives here)
for (uintptr_t va = bss_start; va < bss_end; va += PAGE_SIZE) {
uint64_t pa = va - vaddr + paddr;
vmm_map_page(kernel_pagemap, va, pa, PAGE_READ | PAGE_WRITE | PAGE_NO_EXECUTE, Size4KiB);
}
vmm_switch_pagemap(kernel_pagemap);
printf("VMM: switched to new kernel pagemap\n");
}
void vmm_switch_pagemap(struct pagemap *pagemap) {
uint64_t phys_cr3 = (uintptr_t)pagemap->top_level - MEM_PHYS_OFFSET;
printf("VMM: loading CR3 with PML4 @ 0x%lx\n", phys_cr3);
asm volatile("mov %0, %%cr3" : : "r"((uint64_t)pagemap->top_level - MEM_PHYS_OFFSET) : "memory");
printf("rah");
}
bool vmm_map_page(struct pagemap *pagemap, uint64_t virt, uint64_t phys,
uint64_t flags, enum page_size pg_size) {
spinlock_acquire_or_wait(&pagemap->lock);
// Calculate the indices in the various tables using the virtual address
size_t pml5_entry = (virt & ((uint64_t)0x1FF << 48)) >> 48;
size_t pml4_entry = (virt & ((uint64_t)0x1FF << 39)) >> 39;
size_t pml3_entry = (virt & ((uint64_t)0x1FF << 30)) >> 30;
size_t pml2_entry = (virt & ((uint64_t)0x1FF << 21)) >> 21;
size_t pml1_entry = (virt & ((uint64_t)0x1FF << 12)) >> 12;
uint64_t *pml5, *pml4, *pml3, *pml2, *pml1;
if (paging_mode_request.response->mode == LIMINE_PAGING_MODE_X86_64_5LVL) {
pml5 = pagemap->top_level;
goto level5;
} else {
pml4 = pagemap->top_level;
goto level4;
}
level5:
pml4 = get_next_level(pml5, pml5_entry, true);
if (pml4 == NULL) {
goto die;
}
level4:
pml3 = get_next_level(pml4, pml4_entry, true);
if (pml3 == NULL) {
goto die;
}
pml2 = get_next_level(pml3, pml3_entry, true);
if (pml2 == NULL) {
goto die;
}
if (pg_size == Size2MiB) {
pml2[pml2_entry] = phys | flags | (1 << 7);
spinlock_drop(&pagemap->lock);
return true;
}
pml1 = get_next_level(pml2, pml2_entry, true);
if (pml1 == NULL) {
die:
spinlock_drop(&pagemap->lock);
return false;
}
pml1[pml1_entry] = phys | flags;
spinlock_drop(&pagemap->lock);
return true; // simplified for this response
}
bool vmm_unmap_page(struct pagemap *pagemap, uintptr_t virt, bool locked) {
if (!locked) {
spinlock_acquire_or_wait(&pagemap->lock);
}
size_t pml5_entry = (virt & ((uint64_t)0x1FF << 48)) >> 48;
size_t pml4_entry = (virt & ((uint64_t)0x1FF << 39)) >> 39;
size_t pml3_entry = (virt & ((uint64_t)0x1FF << 30)) >> 30;
size_t pml2_entry = (virt & ((uint64_t)0x1FF << 21)) >> 21;
size_t pml1_entry = (virt & ((uint64_t)0x1FF << 12)) >> 12;
uint64_t *pml5, *pml4, *pml3, *pml2, *pml1;
if (paging_mode_request.response->mode == LIMINE_PAGING_MODE_X86_64_5LVL) {
pml5 = pagemap->top_level;
goto level5;
} else {
pml4 = pagemap->top_level;
goto level4;
}
level5:
pml4 = get_next_level(pml5, pml5_entry, false);
if (pml4 == NULL) {
goto die;
}
level4:
pml3 = get_next_level(pml4, pml4_entry, false);
if (pml3 == NULL) {
goto die;
}
pml2 = get_next_level(pml3, pml3_entry, false);
if (pml2 == NULL) {
goto die;
}
pml1 = get_next_level(pml2, pml2_entry, false);
if (pml1 == NULL) {
goto die;
}
if ((pml1[pml1_entry] & 1) == 0) {
die:
if (!locked) {
spinlock_drop(&pagemap->lock);
}
return false;
}
pml1[pml1_entry] = 0;
asm volatile("invlpg (%0)" : : "r"(virt) : "memory");
if (!locked) {
spinlock_drop(&pagemap->lock);
}
return true;
}
uint64_t *vmm_virt_to_pte(struct pagemap *pagemap, uintptr_t virt_addr,
bool allocate) {
// spinlock_acquire_or_wait(&pagemap->lock);
size_t pml5_entry = (virt_addr & ((uint64_t)0x1FF << 48)) >> 48;
size_t pml4_entry = (virt_addr & ((uint64_t)0x1FF << 39)) >> 39;
size_t pml3_entry = (virt_addr & ((uint64_t)0x1FF << 30)) >> 30;
size_t pml2_entry = (virt_addr & ((uint64_t)0x1FF << 21)) >> 21;
size_t pml1_entry = (virt_addr & ((uint64_t)0x1FF << 12)) >> 12;
uint64_t *pml5, *pml4, *pml3, *pml2, *pml1;
if (paging_mode_request.response->mode == LIMINE_PAGING_MODE_X86_64_5LVL) {
pml5 = pagemap->top_level;
goto level5;
} else {
pml4 = pagemap->top_level;
goto level4;
}
level5:
pml4 = get_next_level(pml5, pml5_entry, allocate);
if (pml4 == NULL) {
goto die;
}
level4:
pml3 = get_next_level(pml4, pml4_entry, allocate);
if (pml3 == NULL) {
goto die;
}
pml2 = get_next_level(pml3, pml3_entry, allocate);
if (pml2 == NULL) {
goto die;
}
pml1 = get_next_level(pml2, pml2_entry, allocate);
if (pml1 == NULL) {
die:
spinlock_drop(&pagemap->lock);
return NULL;
}
// spinlock_drop(&pagemap->lock);
return &pml1[pml1_entry];
}
uint64_t vmm_virt_to_phys(struct pagemap *pagemap, uint64_t virt) {
spinlock_acquire_or_wait(&pagemap->lock);
uint64_t *pte = vmm_virt_to_pte(pagemap, virt, false);
spinlock_drop(&pagemap->lock);
if (pte == NULL || (((*pte) & ~0xffffffffff000) & 1) == 0)
return INVALID_PHYS;
return ((*pte) & 0xffffffffff000);
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <stdint.h>
#include <limine.h>
#include <stddef.h>
#include <mp/spinlock.h>
#include <stdbool.h>
#include <stdint.h>
#define PAGE_SIZE 4096ULL
extern volatile struct limine_hhdm_request hhdm_request;
#define MEM_PHYS_OFFSET (hhdm_request.response->offset)
extern volatile struct limine_executable_address_request kernel_address_request;
#define INVALID_PHYS 0xffffffffffffffffULL
#define PAGE_READ (1ULL << 0)
#define PAGE_WRITE (1ULL << 1)
#define PAGE_USER (1ULL << 2)
#define PAGE_NO_EXECUTE (1ULL << 63)
struct pagemap {
spinlock_t lock;
uint64_t *top_level;
};
extern struct pagemap *kernel_pagemap;
enum page_size { Size4KiB, Size2MiB };
void vmm_init(struct limine_memmap_entry **memmap, size_t memmap_entries);
void vmm_switch_pagemap(struct pagemap *pagemap);
bool vmm_map_page(struct pagemap *pagemap, uint64_t virt, uint64_t phys,
uint64_t flags, enum page_size pg_size);
uint64_t vmm_virt_to_phys(struct pagemap *pagemap, uint64_t virt);
+26
View File
@@ -0,0 +1,26 @@
#include "spinlock.h"
void spinlock_init(spinlock_t *lock) {
atomic_flag_clear(&lock->flag);
}
void spinlock_acquire_or_wait(spinlock_t *lock) {
while (atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire))
asm volatile("pause" ::: "memory");
}
void spinlock_drop(spinlock_t *lock) {
atomic_flag_clear_explicit(&lock->flag, memory_order_release);
}
void spinlock_acquire_irqsave(spinlock_t *lock, uint64_t *flags) {
uint64_t f;
asm volatile("pushfq; pop %0; cli" : "=r"(f) :: "memory");
*flags = f;
spinlock_acquire_or_wait(lock);
}
void spinlock_release_irqrestore(spinlock_t *lock, uint64_t flags) {
spinlock_drop(lock);
asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc");
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <stdatomic.h>
#include <stdint.h>
typedef struct {
atomic_flag flag;
} spinlock_t;
#define SPINLOCK_INIT ((spinlock_t){ .flag = ATOMIC_FLAG_INIT })
void spinlock_init(spinlock_t *lock);
void spinlock_acquire_or_wait(spinlock_t *lock);
void spinlock_drop(spinlock_t *lock);
// Old IRQ-safe API still available for compatibility
void spinlock_acquire_irqsave(spinlock_t *lock, uint64_t *flags);
void spinlock_release_irqrestore(spinlock_t *lock, uint64_t flags);
+139
View File
@@ -0,0 +1,139 @@
#include <stdarg.h>
#include <stdbool.h>
#include "stdio.h"
#include "debug.h"
#include "video/render.h"
#include "arch/x86_64/e9.h"
#include "mp/spinlock.h"
static const uint32_t g_LogSeverityColors[] =
{
[LVL_DEBUG] = 0xAAAAAA, // light gray
[LVL_INFO] = 0xFFFFFF, // white
[LVL_WARN] = 0xFFFF00, // yellow
[LVL_ERROR] = 0xFF0000, // red
[LVL_CRITICAL] = 0xFFFFFF, // white (can do red background separately if you want)
};
static spinlock_t s_printf_lock = SPINLOCK_INIT;
void fputc(char c)
{
putchar(c);
e9_putc(c);
}
void fputs(const char* str)
{
const char* s = str;
while (*s) fputc(*s++);
}
void fputs_colored(const char* str, uint32_t color) {
while (*str) putchar_colored(*str++, color);
while (*str) fputc(*str++);
}
const char g_HexChars[] = "0123456789abcdef";
void fprintf_unsigned(uint64_t number, int radix)
{
char buffer[32];
int pos = 0;
do {
buffer[pos++] = g_HexChars[number % radix];
number /= radix;
} while (number > 0);
while (--pos >= 0) fputc(buffer[pos]);
}
void fprintf_signed(int64_t number, int radix)
{
if (number < 0) {
fputc('-');
fprintf_unsigned(-number, radix);
} else {
fprintf_unsigned(number, radix);
}
}
void vfprintf(const char* fmt, va_list args)
{
int state = 0; // normal
int length = 0; // default
int radix = 10;
bool sign = false;
bool number = false;
while (*fmt) {
switch (state) {
case 0: // normal
if (*fmt == '%') state = 1;
else fputc(*fmt);
break;
case 1: // length
if (*fmt == 'l') { length = 3; state = 4; }
else if (*fmt == 'h') { length = 2; state = 4; }
else goto spec;
break;
case 4: // spec
spec:
switch (*fmt) {
case 'c': fputc((char)va_arg(args,int)); break;
case 's': fputs(va_arg(args,const char*)); break;
case 'd':
case 'i': sign = true; number = true; radix = 10; break;
case 'u': sign = false; number = true; radix = 10; break;
case 'x':
case 'X': sign = false; number = true; radix = 16; break;
case 'p': number = true; sign = false; radix = 16; break;
case 'o': sign = false; number = true; radix = 8; break;
case '%': fputc('%'); break;
}
if (number) {
if (sign) fprintf_signed(va_arg(args,long), radix);
else fprintf_unsigned(va_arg(args,unsigned long), radix);
}
state = 0;
length = 0;
number = false;
sign = false;
break;
}
fmt++;
}
}
void printf(const char* fmt, ...)
{
uint64_t flags;
spinlock_acquire_irqsave(&s_printf_lock, &flags);
va_list args;
va_start(args, fmt);
vfprintf(fmt, args);
va_end(args);
spinlock_release_irqrestore(&s_printf_lock, flags);
}
void fprintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(fmt, args);
va_end(args);
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <stdarg.h>
#include <stdint.h>
void printf(const char* fmt, ...);
void fputs(const char* str);
void fputc(char c);
void vfprintf(const char* fmt, va_list args);
void fprintf(const char* fmt, ...);
void fputs_colored(const char* str, uint32_t color);
+233
View File
@@ -0,0 +1,233 @@
#include "string.h"
#include <stdint.h>
#include <stddef.h>
const char* strchr(const char* str, char chr)
{
if (str == NULL)
return NULL;
while (*str)
{
if (*str == chr)
return str;
++str;
}
return NULL;
}
char* strcpy(char* dst, const char* src)
{
char* origDst = dst;
if (dst == NULL)
return NULL;
if (src == NULL)
{
*dst = '\0';
return dst;
}
while (*src)
{
*dst = *src;
++src;
++dst;
}
*dst = '\0';
return origDst;
}
unsigned strlen(const char* str)
{
unsigned len = 0;
while (*str)
{
++len;
++str;
}
return len;
}
int strcmp(const char* a, const char* b)
{
if (a == NULL && b == NULL)
return 0;
if (a == NULL || b == NULL)
return -1;
while (*a && *b && *a == *b)
{
++a;
++b;
}
return (*a) - (*b);
}
char* strcat(char* dst, const char* src)
{
char* origDst = dst;
if (dst == NULL)
return NULL;
if (src == NULL)
return dst;
// move dst pointer to end of existing string
while (*dst)
{
++dst;
}
// copy src into the end
while (*src)
{
*dst = *src;
++dst;
++src;
}
// null-terminate
*dst = '\0';
return origDst;
}
char* strncpy(char* dst, const char* src, size_t n)
{
char* origDst = dst;
if (dst == NULL)
return NULL;
if (src == NULL)
{
while (n > 0)
{
*dst = '\0';
++dst;
--n;
}
return origDst;
}
while (n > 0 && *src)
{
*dst = *src;
++dst;
++src;
--n;
}
// pad remaining space with '\0'
while (n > 0)
{
*dst = '\0';
++dst;
--n;
}
return origDst;
}
int strncmp(const char* a, const char* b, size_t n)
{
if (n == 0)
return 0;
if (a == NULL && b == NULL)
return 0;
if (a == NULL)
return -1;
if (b == NULL)
return 1;
while (n > 0 && *a && *b && (*a == *b))
{
++a;
++b;
--n;
}
if (n == 0)
return 0;
return ((unsigned char)*a) - ((unsigned char)*b);
}
wchar_t* utf16_to_codepoint(wchar_t* string, int* codepoint)
{
int c1 = *string;
++string;
if (c1 >= 0xd800 && c1 < 0xdc00) {
int c2 = *string;
++string;
*codepoint = ((c1 & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000;
}
*codepoint = c1;
return string;
}
/* Encoding
The following byte sequences are used to represent a
character. The sequence to be used depends on the UCS code
number of the character:
0x00000000 - 0x0000007F:
0xxxxxxx
0x00000080 - 0x000007FF:
110xxxxx 10xxxxxx
0x00000800 - 0x0000FFFF:
1110xxxx 10xxxxxx 10xxxxxx
0x00010000 - 0x001FFFFF:
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
[... removed obsolete five and six byte forms ...]
The xxx bit positions are filled with the bits of the
character code number in binary representation. Only the
shortest possible multibyte sequence which can represent the
code number of the character can be used.
The UCS code values 0xd8000xdfff (UTF-16 surrogates) as well
as 0xfffe and 0xffff (UCS noncharacters) should not appear in
conforming UTF-8 streams.
*/
char* codepoint_to_utf8(int codepoint, char* stringOutput)
{
if (codepoint <= 0x7F) {
*stringOutput = (char)codepoint;
}
else if (codepoint <= 0x7FF) {
*stringOutput++ = 0xC0 | ((codepoint >> 6) & 0x1F);
*stringOutput++ = 0x80 | (codepoint & 0x3F);
}
else if (codepoint <= 0xFFFF) {
*stringOutput++ = 0xE0 | ((codepoint >> 12) & 0xF);
*stringOutput++ = 0x80 | ((codepoint >> 6) & 0x3F);
*stringOutput++ = 0x80 | (codepoint & 0x3F);
}
else if (codepoint <= 0x1FFFFF) {
*stringOutput++ = 0xF0 | ((codepoint >> 18) & 0x7);
*stringOutput++ = 0x80 | ((codepoint >> 12) & 0x3F);
*stringOutput++ = 0x80 | ((codepoint >> 6) & 0x3F);
*stringOutput++ = 0x80 | (codepoint & 0x3F);
}
return stringOutput;
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <stddef.h>
const char* strchr(const char* str, char chr);
char* strcpy(char* dst, const char* src);
unsigned strlen(const char* str);
int strcmp(const char* a, const char* b);
char* strncpy(char* dst, const char* src, size_t n);
char* strcat(char* dst, const char* src);
int strncmp(const char* a, const char* b, size_t n);
wchar_t* utf16_to_codepoint(wchar_t* string, int* codepoint);
char* codepoint_to_utf8(int codepoint, char* stringOutput);
+76
View File
@@ -0,0 +1,76 @@
#include <stdint.h>
#include "stdio.h"
#include "fs/vfs.h"
#define MSR_EFER 0xC0000080
#define MSR_STAR 0xC0000081
#define MSR_LSTAR 0xC0000082
#define MSR_SFMASK 0xC0000084
#define EFER_SCE (1 << 0)
static inline void wrmsr(uint32_t msr, uint64_t value)
{
uint32_t lo = value & 0xFFFFFFFF;
uint32_t hi = value >> 32;
asm volatile("wrmsr"
:
: "c"(msr), "a"(lo), "d"(hi));
}
static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t lo, hi;
asm volatile("rdmsr"
: "=a"(lo), "=d"(hi)
: "c"(msr));
return ((uint64_t)hi << 32) | lo;
}
void syscall_handler(uint64_t rax, // syscall num
uint64_t rdi, // arg1
uint64_t rsi, // arg2
uint64_t rdx, // arg3
uint64_t r10, // arg4
uint64_t r8, // arg5
uint64_t r9) // arg6
{
switch (rax)
{
case 1: // write (int fd, const void *buf, size_t count);
int c = (char)rdi;
printf("%c", c);
break;
case 2:
// exit
break;
default:
break;
}
}
void syscall_init(void)
{
extern void syscall_entry(void);
uint64_t kernel_cs = 0x08;
uint64_t user_cs = 0x1B;
uint64_t star =
((uint64_t)kernel_cs << 32) |
((uint64_t)user_cs << 48);
wrmsr(MSR_STAR, star);
wrmsr(MSR_LSTAR, (uint64_t)syscall_entry);
uint64_t efer = rdmsr(MSR_EFER);
efer |= (1 << 0); // SYSCALL/SYSRET enable
wrmsr(MSR_EFER, efer);
// disable interrupts on syscall entry
wrmsr(MSR_SFMASK, (1 << 9));
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void syscall_init(void);
+30
View File
@@ -0,0 +1,30 @@
.global syscall_entry
syscall_entry:
swapgs
push %rcx
push %r11
# Save original args before we clobber them
push %rdi # orig rdi (arg1)
push %rsi # orig rsi (arg2)
push %rdx # orig rdx (arg3)
# Handle r8/r9 before r8 gets clobbered
mov %r8, %r9 # r9 = orig r8 (6th param)
mov %r10, %r8 # r8 = orig r10 (5th param)
# Pop in reverse order to place into correct SysV registers
pop %rcx # rcx = orig rdx (4th param)
pop %rdx # rdx = orig rsi (3rd param)
pop %rsi # rsi = orig rdi (2nd param)
mov %rax, %rdi # rdi = rax (1st param = syscall number)
call syscall_handler
pop %r11
pop %rcx
swapgs
sysretq
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define SIZE(array) (sizeof(array) / sizeof(array[0]))
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#define FLAG_SET(x, flag) x |= (flag)
#define FLAG_UNSET(x, flag) x &= ~(flag)
+457
View File
@@ -0,0 +1,457 @@
#pragma once
#include <stdint.h>
unsigned char zap_light16_psf[] = {
0x36, 0x04, 0x02, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x5d, 0x7d, 0x7b,
0x77, 0x77, 0x7f, 0x77, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x22, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7f, 0x04, 0x08, 0x10, 0x7f, 0x20,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40,
0x20, 0x10, 0x08, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c,
0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
0x10, 0x11, 0x12, 0x04, 0x08, 0x12, 0x26, 0x4a, 0x0f, 0x02, 0x02, 0x00,
0x00, 0x00, 0x10, 0x30, 0x10, 0x11, 0x12, 0x04, 0x08, 0x10, 0x26, 0x49,
0x02, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x08, 0x30, 0x09, 0x72, 0x04,
0x08, 0x12, 0x26, 0x4a, 0x0f, 0x02, 0x02, 0x00, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, 0x00, 0x07, 0x08,
0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08,
0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0xa4, 0xa4, 0x48, 0x10, 0x10, 0x2a, 0x55, 0x55, 0x8a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf1, 0x5b, 0x55, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x08, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x12, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24,
0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
0x24, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x00,
0x42, 0x3c, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x00, 0x00, 0x3a, 0x46, 0x42,
0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x08, 0x00, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x30,
0x0c, 0x02, 0x42, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x3c, 0x08, 0x08, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24,
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x24,
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x49, 0x48, 0x48,
0x3e, 0x09, 0x09, 0x49, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x31,
0x4a, 0x4a, 0x34, 0x08, 0x08, 0x16, 0x29, 0x29, 0x46, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x24, 0x18, 0x28, 0x45, 0x42, 0x46,
0x39, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08,
0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00,
0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10,
0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x2a,
0x1c, 0x2a, 0x49, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x4a,
0x52, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x1c,
0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x0c, 0x14, 0x24, 0x44, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42,
0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08,
0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20,
0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x04,
0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
0x22, 0x4a, 0x56, 0x52, 0x52, 0x52, 0x4e, 0x20, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42,
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c,
0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e,
0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60,
0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x63, 0x63, 0x55, 0x55, 0x49, 0x49, 0x41, 0x41,
0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52,
0x4a, 0x4a, 0x46, 0x46, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x5a, 0x66, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49,
0x55, 0x55, 0x63, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
0x42, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22,
0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62,
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40,
0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0x10, 0x7c, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x42, 0x3c,
0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x18, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04,
0x00, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38,
0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44,
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x46,
0x3a, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x41, 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x49, 0x49, 0x49, 0x49, 0x49,
0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x24,
0x18, 0x18, 0x24, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x08, 0x08, 0x08, 0x30,
0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x30, 0x08, 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x08, 0x08,
0x08, 0x30, 0x00, 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0c, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42,
0x42, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42,
0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18,
0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x32, 0x4c, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42,
0x42, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42,
0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18,
0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x28, 0x48, 0x48, 0x7e, 0x48, 0x48, 0x48, 0x48,
0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40,
0x40, 0x40, 0x42, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x30, 0x0c, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00,
0x0c, 0x30, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
0x7e, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00,
0x30, 0x0c, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x3e, 0x00, 0x00, 0x00, 0x06, 0x18, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0xf2,
0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x42,
0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46, 0x42, 0x00, 0x00, 0x00,
0x30, 0x0c, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x32, 0x4c, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x3a, 0x44, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x22,
0x5c, 0x40, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x06, 0x18, 0x00, 0x41,
0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x4c, 0x50, 0x50,
0x4c, 0x42, 0x42, 0x52, 0x4c, 0x00, 0x00, 0x00, 0xaa, 0x55, 0xaa, 0x55,
0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x49, 0x48,
0x48, 0x48, 0x48, 0x49, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1c,
0x20, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x22, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x11, 0x20, 0x7e, 0x20, 0x7c, 0x20, 0x11,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08,
0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x24, 0x18, 0x00, 0x3c,
0x42, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x22, 0x20, 0x18, 0x24, 0x22, 0x22, 0x12, 0x0c, 0x02,
0x22, 0x1c, 0x00, 0x00, 0x00, 0x24, 0x18, 0x00, 0x00, 0x3c, 0x42, 0x40,
0x30, 0x0c, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24,
0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x22,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5,
0xb9, 0xa9, 0xa5, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08,
0x08, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44,
0x04, 0x18, 0x20, 0x40, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x5a, 0x40, 0x40, 0x40,
0x00, 0x00, 0x00, 0x3e, 0x7a, 0x7a, 0x7a, 0x7a, 0x3a, 0x0a, 0x0a, 0x0a,
0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x00,
0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x37, 0x48, 0x48, 0x48, 0x4e, 0x48, 0x48, 0x48, 0x48,
0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x49, 0x49,
0x4f, 0x48, 0x48, 0x49, 0x36, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x41,
0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22,
0x88, 0x22, 0x88, 0x22, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0x10, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x04, 0xf4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x17, 0x10, 0x1f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xf4,
0x04, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xf4, 0x04, 0xf4, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xf7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xf7, 0x00, 0xf7, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
0x7f, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x04, 0xfe, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46,
0x3a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x02,
0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00,
0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46,
0x3a, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x02,
0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18,
0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x49, 0x09, 0x3f, 0x48, 0x48, 0x49,
0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40,
0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, 0x30, 0x0c, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x18, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00,
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x18, 0x64, 0x02, 0x3a, 0x46,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00,
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x3c, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x10, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62,
0x3c, 0x40, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46,
0x3a, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x42, 0x3c,
0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62,
0x5c, 0x40, 0x40, 0x40, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x42, 0x3c, 0xfd, 0xff, 0xff, 0xff,
0xc0, 0x03, 0xff, 0xff, 0x60, 0x22, 0xff, 0xff, 0x64, 0x22, 0xff, 0xff,
0x65, 0x22, 0xff, 0xff, 0xa0, 0x25, 0xac, 0x25, 0xae, 0x25, 0xfc, 0x25,
0xfe, 0x25, 0x1b, 0x2b, 0x0e, 0x22, 0xff, 0xff, 0xc6, 0x25, 0x66, 0x26,
0x25, 0x2b, 0x27, 0x2b, 0xff, 0xff, 0xbc, 0x00, 0xff, 0xff, 0xbd, 0x00,
0xff, 0xff, 0xbe, 0x00, 0xff, 0xff, 0xa6, 0x00, 0xff, 0xff, 0xa8, 0x00,
0xff, 0xff, 0xb8, 0x00, 0xff, 0xff, 0x92, 0x01, 0xff, 0xff, 0x20, 0x20,
0xff, 0xff, 0x21, 0x20, 0xff, 0xff, 0x30, 0x20, 0xff, 0xff, 0x22, 0x21,
0xff, 0xff, 0x26, 0x20, 0xff, 0xff, 0x39, 0x20, 0xff, 0xff, 0x3a, 0x20,
0xff, 0xff, 0x1c, 0x20, 0x1f, 0x20, 0x36, 0x20, 0xff, 0xff, 0x1d, 0x20,
0xba, 0x02, 0xdd, 0x02, 0xee, 0x02, 0x33, 0x20, 0xff, 0xff, 0x1e, 0x20,
0xff, 0xff, 0x42, 0x2e, 0xff, 0xff, 0x41, 0x2e, 0xce, 0x02, 0xff, 0xff,
0x1e, 0x01, 0xff, 0xff, 0x1f, 0x01, 0xff, 0xff, 0x30, 0x01, 0xff, 0xff,
0x31, 0x01, 0xff, 0xff, 0x5e, 0x01, 0xff, 0xff, 0x5f, 0x01, 0xff, 0xff,
0x20, 0x00, 0xa0, 0x00, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20,
0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20,
0x0a, 0x20, 0x2f, 0x20, 0x5f, 0x20, 0xff, 0xff, 0x21, 0x00, 0xff, 0xff,
0x22, 0x00, 0xff, 0xff, 0x23, 0x00, 0xff, 0xff, 0x24, 0x00, 0xff, 0xff,
0x25, 0x00, 0xff, 0xff, 0x26, 0x00, 0xff, 0xff, 0x27, 0x00, 0xb4, 0x00,
0xb9, 0x02, 0xbc, 0x02, 0xca, 0x02, 0x19, 0x20, 0x32, 0x20, 0xff, 0xff,
0x28, 0x00, 0xff, 0xff, 0x29, 0x00, 0xff, 0xff, 0x2a, 0x00, 0x4e, 0x20,
0x17, 0x22, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2c, 0x00, 0xcf, 0x02,
0x1a, 0x20, 0xff, 0xff, 0x2d, 0x00, 0xad, 0x00, 0x10, 0x20, 0x11, 0x20,
0x12, 0x20, 0x13, 0x20, 0x43, 0x20, 0x12, 0x22, 0xff, 0xff, 0x2e, 0x00,
0x24, 0x20, 0xff, 0xff, 0x2f, 0x00, 0x44, 0x20, 0x15, 0x22, 0xff, 0xff,
0x30, 0x00, 0xff, 0xff, 0x31, 0x00, 0xff, 0xff, 0x32, 0x00, 0xff, 0xff,
0x33, 0x00, 0xff, 0xff, 0x34, 0x00, 0xff, 0xff, 0x35, 0x00, 0xff, 0xff,
0x36, 0x00, 0xff, 0xff, 0x37, 0x00, 0xff, 0xff, 0x38, 0x00, 0xff, 0xff,
0x39, 0x00, 0xff, 0xff, 0x3a, 0x00, 0x36, 0x22, 0xff, 0xff, 0x3b, 0x00,
0xff, 0xff, 0x3c, 0x00, 0xff, 0xff, 0x3d, 0x00, 0x40, 0x2e, 0xff, 0xff,
0x3e, 0x00, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x40, 0x00, 0xff, 0xff,
0x41, 0x00, 0xff, 0xff, 0x42, 0x00, 0xff, 0xff, 0x43, 0x00, 0xff, 0xff,
0x44, 0x00, 0xff, 0xff, 0x45, 0x00, 0xff, 0xff, 0x46, 0x00, 0xff, 0xff,
0x47, 0x00, 0xff, 0xff, 0x48, 0x00, 0xff, 0xff, 0x49, 0x00, 0xff, 0xff,
0x4a, 0x00, 0xff, 0xff, 0x4b, 0x00, 0x2a, 0x21, 0xff, 0xff, 0x4c, 0x00,
0xff, 0xff, 0x4d, 0x00, 0xff, 0xff, 0x4e, 0x00, 0xff, 0xff, 0x4f, 0x00,
0xff, 0xff, 0x50, 0x00, 0xff, 0xff, 0x51, 0x00, 0xff, 0xff, 0x52, 0x00,
0xff, 0xff, 0x53, 0x00, 0xff, 0xff, 0x54, 0x00, 0xff, 0xff, 0x55, 0x00,
0xff, 0xff, 0x56, 0x00, 0xff, 0xff, 0x57, 0x00, 0xff, 0xff, 0x58, 0x00,
0xff, 0xff, 0x59, 0x00, 0xff, 0xff, 0x5a, 0x00, 0xff, 0xff, 0x5b, 0x00,
0xff, 0xff, 0x5c, 0x00, 0xf5, 0x29, 0xff, 0xff, 0x5d, 0x00, 0xff, 0xff,
0x5e, 0x00, 0xc4, 0x02, 0xc6, 0x02, 0x03, 0x23, 0xff, 0xff, 0x5f, 0x00,
0xff, 0xff, 0x60, 0x00, 0xbb, 0x02, 0xbd, 0x02, 0xcb, 0x02, 0x18, 0x20,
0x1b, 0x20, 0x35, 0x20, 0xff, 0xff, 0x61, 0x00, 0xff, 0xff, 0x62, 0x00,
0xff, 0xff, 0x63, 0x00, 0xff, 0xff, 0x64, 0x00, 0xff, 0xff, 0x65, 0x00,
0xff, 0xff, 0x66, 0x00, 0xff, 0xff, 0x67, 0x00, 0xff, 0xff, 0x68, 0x00,
0xff, 0xff, 0x69, 0x00, 0xff, 0xff, 0x6a, 0x00, 0xff, 0xff, 0x6b, 0x00,
0xff, 0xff, 0x6c, 0x00, 0xff, 0xff, 0x6d, 0x00, 0xff, 0xff, 0x6e, 0x00,
0xff, 0xff, 0x6f, 0x00, 0xff, 0xff, 0x70, 0x00, 0xff, 0xff, 0x71, 0x00,
0xff, 0xff, 0x72, 0x00, 0xff, 0xff, 0x73, 0x00, 0xff, 0xff, 0x74, 0x00,
0xff, 0xff, 0x75, 0x00, 0xff, 0xff, 0x76, 0x00, 0xff, 0xff, 0x77, 0x00,
0xff, 0xff, 0x78, 0x00, 0xff, 0xff, 0x79, 0x00, 0xff, 0xff, 0x7a, 0x00,
0xff, 0xff, 0x7b, 0x00, 0xff, 0xff, 0x7c, 0x00, 0x23, 0x22, 0xff, 0xff,
0x7d, 0x00, 0xff, 0xff, 0x7e, 0x00, 0xdc, 0x02, 0xff, 0xff, 0x22, 0x20,
0x19, 0x22, 0xcf, 0x25, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xc1, 0x00,
0xff, 0xff, 0xc2, 0x00, 0xff, 0xff, 0xc3, 0x00, 0xff, 0xff, 0xc4, 0x00,
0xff, 0xff, 0xc5, 0x00, 0x2b, 0x21, 0xff, 0xff, 0xc6, 0x00, 0xff, 0xff,
0xc7, 0x00, 0xff, 0xff, 0xc8, 0x00, 0xff, 0xff, 0xc9, 0x00, 0xff, 0xff,
0xca, 0x00, 0xff, 0xff, 0xcb, 0x00, 0xff, 0xff, 0xcc, 0x00, 0xff, 0xff,
0xcd, 0x00, 0xff, 0xff, 0xce, 0x00, 0xff, 0xff, 0xcf, 0x00, 0xff, 0xff,
0xd0, 0x00, 0x10, 0x01, 0xff, 0xff, 0xd1, 0x00, 0xff, 0xff, 0xd2, 0x00,
0xff, 0xff, 0xd3, 0x00, 0xff, 0xff, 0xd4, 0x00, 0xff, 0xff, 0xd5, 0x00,
0xff, 0xff, 0xd6, 0x00, 0xff, 0xff, 0xd7, 0x00, 0xff, 0xff, 0xd8, 0x00,
0xff, 0xff, 0xd9, 0x00, 0xff, 0xff, 0xda, 0x00, 0xff, 0xff, 0xdb, 0x00,
0xff, 0xff, 0xdc, 0x00, 0xff, 0xff, 0xdd, 0x00, 0xff, 0xff, 0xde, 0x00,
0xff, 0xff, 0xdf, 0x00, 0xff, 0xff, 0x92, 0x25, 0xff, 0xff, 0xa1, 0x00,
0xff, 0xff, 0xa2, 0x00, 0xff, 0xff, 0xa3, 0x00, 0xff, 0xff, 0xac, 0x20,
0xff, 0xff, 0xa5, 0x00, 0xff, 0xff, 0x60, 0x01, 0xff, 0xff, 0xa7, 0x00,
0xff, 0xff, 0x61, 0x01, 0xff, 0xff, 0xa9, 0x00, 0xff, 0xff, 0xaa, 0x00,
0xff, 0xff, 0xab, 0x00, 0xff, 0xff, 0xac, 0x00, 0xff, 0xff, 0xa4, 0x00,
0xff, 0xff, 0xae, 0x00, 0xff, 0xff, 0xaf, 0x00, 0xc9, 0x02, 0xff, 0xff,
0xb0, 0x00, 0xda, 0x02, 0xff, 0xff, 0xb1, 0x00, 0xff, 0xff, 0xb2, 0x00,
0xff, 0xff, 0xb3, 0x00, 0xff, 0xff, 0x7d, 0x01, 0xff, 0xff, 0xb5, 0x00,
0xbc, 0x03, 0xff, 0xff, 0xb6, 0x00, 0xff, 0xff, 0xb7, 0x00, 0x27, 0x20,
0xc5, 0x22, 0x31, 0x2e, 0xff, 0xff, 0x7e, 0x01, 0xff, 0xff, 0xb9, 0x00,
0xff, 0xff, 0xba, 0x00, 0xff, 0xff, 0xbb, 0x00, 0xff, 0xff, 0x52, 0x01,
0xff, 0xff, 0x53, 0x01, 0xff, 0xff, 0x78, 0x01, 0xff, 0xff, 0xbf, 0x00,
0xff, 0xff, 0x00, 0x25, 0x14, 0x20, 0x15, 0x20, 0xaf, 0x23, 0xff, 0xff,
0x02, 0x25, 0xff, 0xff, 0x0c, 0x25, 0x6d, 0x25, 0xff, 0xff, 0x10, 0x25,
0x6e, 0x25, 0xff, 0xff, 0x14, 0x25, 0x70, 0x25, 0xff, 0xff, 0x18, 0x25,
0x6f, 0x25, 0xff, 0xff, 0x1c, 0x25, 0xff, 0xff, 0x24, 0x25, 0xff, 0xff,
0x2c, 0x25, 0xff, 0xff, 0x34, 0x25, 0xff, 0xff, 0x3c, 0x25, 0xff, 0xff,
0x91, 0x25, 0xff, 0xff, 0xba, 0x23, 0x3e, 0x20, 0xff, 0xff, 0xbb, 0x23,
0xff, 0xff, 0xbc, 0x23, 0xff, 0xff, 0xbd, 0x23, 0xff, 0xff, 0x50, 0x25,
0x01, 0x25, 0xff, 0xff, 0x51, 0x25, 0x03, 0x25, 0xff, 0xff, 0x54, 0x25,
0x0f, 0x25, 0xff, 0xff, 0x57, 0x25, 0x13, 0x25, 0xff, 0xff, 0x5a, 0x25,
0x17, 0x25, 0xff, 0xff, 0x5d, 0x25, 0x1b, 0x25, 0xff, 0xff, 0x60, 0x25,
0x23, 0x25, 0xff, 0xff, 0x63, 0x25, 0x2b, 0x25, 0xff, 0xff, 0x66, 0x25,
0x33, 0x25, 0xff, 0xff, 0x69, 0x25, 0x3b, 0x25, 0xff, 0xff, 0x6c, 0x25,
0x4b, 0x25, 0xff, 0xff, 0x88, 0x25, 0xff, 0xff, 0x91, 0x21, 0xff, 0xff,
0x93, 0x21, 0xff, 0xff, 0x90, 0x21, 0xff, 0xff, 0x92, 0x21, 0xff, 0xff,
0xe0, 0x00, 0xff, 0xff, 0xe1, 0x00, 0xff, 0xff, 0xe2, 0x00, 0xff, 0xff,
0xe3, 0x00, 0xff, 0xff, 0xe4, 0x00, 0xff, 0xff, 0xe5, 0x00, 0xff, 0xff,
0xe6, 0x00, 0xff, 0xff, 0xe7, 0x00, 0xff, 0xff, 0xe8, 0x00, 0xff, 0xff,
0xe9, 0x00, 0xff, 0xff, 0xea, 0x00, 0xff, 0xff, 0xeb, 0x00, 0xff, 0xff,
0xec, 0x00, 0xff, 0xff, 0xed, 0x00, 0xff, 0xff, 0xee, 0x00, 0xff, 0xff,
0xef, 0x00, 0xff, 0xff, 0xf0, 0x00, 0xff, 0xff, 0xf1, 0x00, 0xff, 0xff,
0xf2, 0x00, 0xff, 0xff, 0xf3, 0x00, 0xff, 0xff, 0xf4, 0x00, 0xff, 0xff,
0xf5, 0x00, 0xff, 0xff, 0xf6, 0x00, 0xff, 0xff, 0xf7, 0x00, 0xff, 0xff,
0xf8, 0x00, 0xff, 0xff, 0xf9, 0x00, 0xff, 0xff, 0xfa, 0x00, 0xff, 0xff,
0xfb, 0x00, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xfd, 0x00, 0xff, 0xff,
0xfe, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff
};
unsigned int zap_light16_psf_len = 5312;
typedef struct {
uint8_t magic[2]; // 0x36, 0x04
uint8_t mode;
uint8_t charsize; // bytes per glyph
} PSF1_Header;
+342
View File
@@ -0,0 +1,342 @@
#include <stdint.h>
#include "font.h"
#include <stdarg.h>
#include "render.h"
#include "mm/memory.h"
uint32_t *fb;
uint32_t fb_width;
uint32_t fb_height;
uint32_t fb_pitch;
static int cursor_x = 0;
static int cursor_y = 0;
void put_pixel(int x, int y, uint32_t color) {
fb[y * fb_pitch + x] = color;
}
static void scroll_up(void) {
uint32_t line_pixels = FONT_HEIGHT * fb_pitch;
uint32_t total_pixels = fb_height * fb_pitch;
// Shift everything up by one line
memmove(fb, fb + line_pixels, (total_pixels - line_pixels) * sizeof(uint32_t));
// Clear the last line
memset(fb + (total_pixels - line_pixels), 0, line_pixels * sizeof(uint32_t));
cursor_y -= FONT_HEIGHT;
}
void draw_char_colored(int x, int y, char c, uint32_t color) {
PSF1_Header *font = (PSF1_Header*)(uintptr_t)zap_light16_psf;
uint8_t *glyphs = zap_light16_psf + sizeof(PSF1_Header);
int charsize = font->charsize;
uint8_t *glyph = glyphs + ((unsigned char)c * charsize);
for (int row = 0; row < charsize; row++) {
for (int col = 0; col < 8; col++) {
if (glyph[row] & (0x80 >> col)) {
fb[(y + row) * fb_pitch + (x + col)] = color;
}
}
}
}
void putchar(char c) {
if (c == '\n') {
cursor_x = 0;
cursor_y += FONT_HEIGHT;
if (cursor_y + FONT_HEIGHT > fb_height) scroll_up();
return;
}
draw_char_colored(cursor_x, cursor_y, c, 0xFFFFFF);
cursor_x += FONT_WIDTH;
if (cursor_x >= (int)fb_width) {
cursor_x = 0;
cursor_y += FONT_HEIGHT;
if (cursor_y + FONT_HEIGHT > fb_height) scroll_up();
}
}
void putchar_colored(char c, uint32_t color) {
if (c == '\n') {
cursor_x = 0;
cursor_y += FONT_HEIGHT;
if (cursor_y + FONT_HEIGHT > fb_height) scroll_up();
return;
}
draw_char_colored(cursor_x, cursor_y, c, color);
cursor_x += FONT_WIDTH;
if (cursor_x >= (int)fb_width) {
cursor_x = 0;
cursor_y += FONT_HEIGHT;
if (cursor_y + FONT_HEIGHT > fb_height) scroll_up();
}
}
void print(const char *str) {
while (*str) {
putchar(*str++);
}
}
void itoa(int value, char *buf, int base) {
char *ptr = buf, *ptr1 = buf, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "0123456789ABCDEF"[tmp_value - value * base];
} while (value);
*ptr-- = '\0';
while (ptr1 < ptr) {
tmp_char = *ptr;
*ptr-- = *ptr1;
*ptr1++ = tmp_char;
}
}
static inline uint32_t sample(uint32_t *src, int w, int h, int x, int y)
{
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= w) x = w - 1;
if (y >= h) y = h - 1;
return src[y * w + x];
}
void clear_screen(uint32_t color)
{
uint32_t total = fb_width * fb_height;
for (uint32_t i = 0; i < total; i++)
{
fb[i] = color;
}
cursor_y = 0;
}
void draw_image_bilinear(uint32_t *img, int x0, int y0, int new_w, int new_h)
{
int src_w = img[0];
int src_h = img[1];
uint32_t *src = &img[2];
// fixed-point scale factors (16.16)
uint32_t x_scale = (src_w << 16) / new_w;
uint32_t y_scale = (src_h << 16) / new_h;
for (int y = 0; y < new_h; y++)
{
int sy_fp = y * y_scale;
int sy = sy_fp >> 16;
int fy = (sy_fp >> 8) & 0xFF;
for (int x = 0; x < new_w; x++)
{
int sx_fp = x * x_scale;
int sx = sx_fp >> 16;
int fx = (sx_fp >> 8) & 0xFF;
int x1 = sx + 1;
int y1 = sy + 1;
uint32_t c00 = sample(src, src_w, src_h, sx, sy);
uint32_t c10 = sample(src, src_w, src_h, x1, sy);
uint32_t c01 = sample(src, src_w, src_h, sx, y1);
uint32_t c11 = sample(src, src_w, src_h, x1, y1);
// unpack
uint32_t a00 = (c00 >> 24) & 0xFF;
uint32_t r00 = (c00 >> 16) & 0xFF;
uint32_t g00 = (c00 >> 8) & 0xFF;
uint32_t b00 = (c00) & 0xFF;
uint32_t a10 = (c10 >> 24) & 0xFF;
uint32_t r10 = (c10 >> 16) & 0xFF;
uint32_t g10 = (c10 >> 8) & 0xFF;
uint32_t b10 = (c10) & 0xFF;
uint32_t a01 = (c01 >> 24) & 0xFF;
uint32_t r01 = (c01 >> 16) & 0xFF;
uint32_t g01 = (c01 >> 8) & 0xFF;
uint32_t b01 = (c01) & 0xFF;
uint32_t a11 = (c11 >> 24) & 0xFF;
uint32_t r11 = (c11 >> 16) & 0xFF;
uint32_t g11 = (c11 >> 8) & 0xFF;
uint32_t b11 = (c11) & 0xFF;
// bilinear interpolation weights
uint32_t w00 = (256 - fx) * (256 - fy);
uint32_t w10 = fx * (256 - fy);
uint32_t w01 = (256 - fx) * fy;
uint32_t w11 = fx * fy;
uint32_t a = (a00*w00 + a10*w10 + a01*w01 + a11*w11) >> 16;
uint32_t r = (r00*w00 + r10*w10 + r01*w01 + r11*w11) >> 16;
uint32_t g = (g00*w00 + g10*w10 + g01*w01 + g11*w11) >> 16;
uint32_t b = (b00*w00 + b10*w10 + b01*w01 + b11*w11) >> 16;
int dst_x = x0 + x;
int dst_y = y0 + y;
if (dst_x < 0 || dst_y < 0 ||
dst_x >= (int)fb_width ||
dst_y >= (int)fb_height)
continue;
uint32_t color = (a << 24) | (r << 16) | (g << 8) | b;
// alpha blend with framebuffer
if (a < 255)
{
uint32_t dst = fb[dst_y * fb_pitch + dst_x];
uint32_t dr = (dst >> 16) & 0xFF;
uint32_t dg = (dst >> 8) & 0xFF;
uint32_t db = dst & 0xFF;
uint32_t inv = 255 - a;
r = (r * a + dr * inv) / 255;
g = (g * a + dg * inv) / 255;
b = (b * a + db * inv) / 255;
fb[dst_y * fb_pitch + dst_x] =
(0xFF << 24) | (r << 16) | (g << 8) | b;
}
else
{
fb[dst_y * fb_pitch + dst_x] =
(0xFF << 24) | (r << 16) | (g << 8) | b;
}
}
}
}
void backspace() {
if (cursor_x >= FONT_WIDTH) {
cursor_x -= FONT_WIDTH;
// clear the character cell
for (int y = 0; y < FONT_HEIGHT; y++) {
for (int x = 0; x < FONT_WIDTH; x++) {
fb[(cursor_y + y) * fb_pitch + (cursor_x + x)] = 0;
}
}
}
}
void draw_image(uint32_t *img, int x0, int y0)
{
uint32_t w = img[0];
uint32_t h = img[1];
uint32_t *pixels = &img[2];
for (uint32_t y = 0; y < h; y++) {
for (uint32_t x = 0; x < w; x++) {
int dst_x = x0 + x;
int dst_y = y0 + y;
// bounds check (VERY important in kernel)
if (dst_x < 0 || dst_y < 0 ||
dst_x >= (int)fb_width ||
dst_y >= (int)fb_height)
continue;
uint32_t color = pixels[y * w + x];
// alpha handling (TGA is ARGB in your parser)
uint8_t a = color >> 24;
// fully transparent → skip
if (a == 0)
continue;
// optional: simple alpha blend
if (a < 255) {
uint32_t dst = fb[dst_y * fb_pitch + dst_x];
uint8_t sr = (color >> 16) & 0xFF;
uint8_t sg = (color >> 8) & 0xFF;
uint8_t sb = (color) & 0xFF;
uint8_t dr = (dst >> 16) & 0xFF;
uint8_t dg = (dst >> 8) & 0xFF;
uint8_t db = (dst) & 0xFF;
uint8_t inv = 255 - a;
uint32_t out =
((sr * a + dr * inv) / 255) << 16 |
((sg * a + dg * inv) / 255) << 8 |
((sb * a + db * inv) / 255);
fb[dst_y * fb_pitch + dst_x] = out;
}
else {
// opaque fast path
fb[dst_y * fb_pitch + dst_x] = color;
}
}
}
}
/*void printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char buffer[32];
for (int i = 0; fmt[i] != 0; i++) {
if (fmt[i] == '%') {
i++;
switch (fmt[i]) {
case 'd': {
int val = va_arg(args, int);
itoa(val, buffer, 10);
print(buffer);
break;
}
case 'x': {
int val = va_arg(args, int);
itoa(val, buffer, 16);
print(buffer);
break;
}
case 's': {
char *str = va_arg(args, char*);
print(str);
break;
}
case 'c': {
char c = (char)va_arg(args, int);
putchar(c);
break;
}
}
} else {
putchar(fmt[i]);
}
}
va_end(args);
}*/
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
#define FONT_WIDTH 8
#define FONT_HEIGHT 16
extern uint32_t *fb;
extern uint32_t fb_width;
extern uint32_t fb_height;
extern uint32_t fb_pitch;
void putchar(char c);
void putchar_colored(char c, uint32_t color);
void draw_image(uint32_t *img, int x0, int y0);
void draw_image_bilinear(uint32_t *img, int x0, int y0, int new_w, int new_h);
void clear_screen(uint32_t color);
void backspace();
+253
View File
@@ -0,0 +1,253 @@
#include "mm/memory.h"
#include <stddef.h>
#include <stdint.h>
static inline int ok(int m, int need, int size)
{
return (m >= 0 && need >= 0 && m <= size && size - m >= need);
}
static inline uint32_t read_color(unsigned char *pal, int idx, int bpp)
{
// palette entry size = bpp/8
int step = bpp >> 3;
unsigned char b = pal[idx * step + 0];
unsigned char g = pal[idx * step + 1];
unsigned char r = pal[idx * step + 2];
unsigned char a = (step == 4) ? pal[idx * step + 3] : 0xFF;
return ((uint32_t)a << 24) |
((uint32_t)r << 16) |
((uint32_t)g << 8) |
(uint32_t)b;
}
unsigned int *tga_parse(unsigned char *ptr, int size)
{
if (!ptr || size < 18) return NULL;
int m = 0;
int id_len = ptr[0];
int cmap_type = ptr[1];
int img_type = ptr[2];
int cmap_start = ptr[3] | (ptr[4] << 8);
int cmap_len = ptr[5] | (ptr[6] << 8);
int cmap_bpp = ptr[7];
int w = ptr[12] | (ptr[13] << 8);
int h = ptr[14] | (ptr[15] << 8);
int bpp = ptr[16];
int desc = ptr[17];
if (w <= 0 || h <= 0 || w > 4096 || h > 4096)
return NULL;
if (!ok(18, id_len, size))
return NULL;
m = 18 + id_len;
if (m > size) return NULL;
int flip_y = !(desc & 0x20);
size_t pixels = (size_t)w * (size_t)h;
if (pixels == 0 || pixels > (SIZE_MAX / sizeof(unsigned int)))
return NULL;
unsigned int *out = (unsigned int *)kmalloc((pixels + 2) * sizeof(unsigned int));
if (!out) return NULL;
out[0] = w;
out[1] = h;
size_t i = 0;
unsigned char *palette = NULL;
if (cmap_type == 1)
{
// palette starts immediately after header+id
palette = ptr + m;
size_t pal_size = (size_t)cmap_len * (cmap_bpp >> 3);
if (!ok(m, pal_size, size)) {
kfree(out);
return NULL;
}
m += pal_size;
}
// =========================
// TYPE 2 (TRUECOLOR)
// =========================
if (img_type == 2)
{
int bytespp = bpp >> 3;
if (bytespp != 3 && bytespp != 4) goto fail;
for (int y = 0; y < h; y++)
{
int row = flip_y ? (h - 1 - y) : y;
for (int x = 0; x < w; x++)
{
if (!ok(m, bytespp, size)) goto fail;
unsigned char b = ptr[m + 0];
unsigned char g = ptr[m + 1];
unsigned char r = ptr[m + 2];
unsigned char a = (bytespp == 4) ? ptr[m + 3] : 0xFF;
m += bytespp;
out[2 + (size_t)row * w + x] =
((uint32_t)a << 24) |
((uint32_t)r << 16) |
((uint32_t)g << 8) |
(uint32_t)b;
}
}
}
// =========================
// TYPE 3 (GRAYSCALE)
// =========================
else if (img_type == 3)
{
for (size_t idx = 0; idx < pixels; idx++)
{
if (!ok(m, 1, size)) goto fail;
unsigned char v = ptr[m++];
out[2 + idx] =
0xFF000000 |
(v << 16) |
(v << 8) |
v;
}
}
// =========================
// TYPE 1 (PALETTED)
// =========================
else if (img_type == 1)
{
if (!palette) goto fail;
for (size_t idx = 0; idx < pixels; idx++)
{
if (!ok(m, 1, size)) goto fail;
unsigned char index = ptr[m++];
out[2 + idx] = read_color(palette, index, cmap_bpp);
}
}
// =========================
// TYPE 9/10/11 (RLE)
// =========================
else if (img_type == 9 || img_type == 10 || img_type == 11)
{
int bytespp = (img_type == 9) ? 1 : (bpp >> 3);
if (img_type != 9 && bytespp != 3 && bytespp != 4) goto fail;
while (i < pixels)
{
if (!ok(m, 1, size)) goto fail;
unsigned char packet = ptr[m++];
int count = (packet & 0x7F) + 1;
if (count > (int)(pixels - i))
count = (int)(pixels - i);
if (packet & 0x80)
{
// RLE
if (!ok(m, bytespp, size)) goto fail;
uint32_t color;
if (img_type == 9)
{
color = read_color(palette, ptr[m], cmap_bpp);
m += 1;
}
else if (img_type == 11)
{
unsigned char v = ptr[m++];
color = 0xFF000000 | (v << 16) | (v << 8) | v;
}
else
{
unsigned char b = ptr[m + 0];
unsigned char g = ptr[m + 1];
unsigned char r = ptr[m + 2];
unsigned char a = (bytespp == 4) ? ptr[m + 3] : 0xFF;
m += bytespp;
color =
((uint32_t)a << 24) |
((uint32_t)r << 16) |
((uint32_t)g << 8) |
(uint32_t)b;
}
for (int k = 0; k < count; k++)
out[2 + i++] = color;
}
else
{
// RAW
for (int k = 0; k < count; k++)
{
if (!ok(m, bytespp, size)) goto fail;
uint32_t color;
if (img_type == 9)
{
color = read_color(palette, ptr[m++], cmap_bpp);
}
else if (img_type == 11)
{
unsigned char v = ptr[m++];
color = 0xFF000000 | (v << 16) | (v << 8) | v;
}
else
{
unsigned char b = ptr[m + 0];
unsigned char g = ptr[m + 1];
unsigned char r = ptr[m + 2];
unsigned char a = (bytespp == 4) ? ptr[m + 3] : 0xFF;
m += bytespp;
color =
((uint32_t)a << 24) |
((uint32_t)r << 16) |
((uint32_t)g << 8) |
(uint32_t)b;
}
out[2 + i++] = color;
}
}
}
}
else
{
goto fail;
}
return out;
fail:
kfree(out);
return NULL;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
typedef struct {
unsigned char magic1; // must be zero
unsigned char colormap; // must be zero
unsigned char encoding; // must be 2
unsigned short cmaporig, cmaplen; // must be zero
unsigned char cmapent; // must be zero
unsigned short x; // must be zero
unsigned short y; // image's height
unsigned short h; // image's height
unsigned short w; // image's width
unsigned char bpp; // must be 32
unsigned char pixeltype; // must be 40
} __attribute__((packed)) tga_header_t;
unsigned int *tga_parse(unsigned char *ptr, int size);