aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/wm.c49
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/drivers/ide.c4
-rw-r--r--kernel/drivers/interrupts.c11
-rw-r--r--kernel/drivers/keyboard.c41
-rw-r--r--kernel/drivers/mouse.c147
-rw-r--r--kernel/features/event.c61
-rw-r--r--kernel/features/fs.c171
-rw-r--r--kernel/features/load.c26
-rw-r--r--kernel/features/proc.c182
-rw-r--r--kernel/features/syscall.c36
-rw-r--r--kernel/inc/event.h19
-rw-r--r--kernel/inc/fs.h33
-rw-r--r--kernel/inc/keyboard.h1
-rw-r--r--kernel/inc/load.h55
-rw-r--r--kernel/inc/proc.h25
-rw-r--r--kernel/main.c1
-rw-r--r--libc/Makefile1
-rw-r--r--libc/inc/assert.h3
-rw-r--r--libc/inc/mem.h20
-rw-r--r--libc/inc/stack.h28
-rw-r--r--libc/inc/sys.h38
-rw-r--r--libc/mem.c355
-rw-r--r--libc/stack.c125
-rw-r--r--libgui/gfx.c8
-rw-r--r--libgui/gui.c20
-rw-r--r--libgui/inc/gfx.h8
-rw-r--r--libgui/png.c8
28 files changed, 985 insertions, 494 deletions
diff --git a/apps/wm.c b/apps/wm.c
index da5153c..9b7631d 100644
--- a/apps/wm.c
+++ b/apps/wm.c
@@ -88,7 +88,7 @@ static void kill_focused()
{
if (!focused)
return;
- msg_send(focused->pid, GUI_KILL, NULL);
+ //msg_send(focused->pid, GUI_KILL, NULL);
remove_context(focused);
focused = context_at(mouse_x, mouse_y);
}
@@ -162,7 +162,7 @@ static void handle_keyboard(struct event_keyboard *event)
msg->press = event->press;
msg->scancode = event->scancode;
- msg_send(focused->pid, GUI_KEYBOARD, msg);
+ //msg_send(focused->pid, GUI_KEYBOARD, msg);
}
static int mouse_skip = 0;
@@ -237,7 +237,7 @@ static void handle_mouse(struct event_mouse *event)
focused = resized;
struct gui_event_resize *msg = malloc(sizeof(*msg));
msg->new_ctx = resized;
- msg_send(resized->pid, GUI_RESIZE, msg);
+ //msg_send(resized->pid, GUI_RESIZE, msg);
redraw_all();
}
}
@@ -255,7 +255,7 @@ static void handle_mouse(struct event_mouse *event)
msg->but1 = event->but1;
msg->but2 = event->but2;
msg->but3 = event->but3;
- msg_send(focused->pid, GUI_MOUSE, msg);
+ //msg_send(focused->pid, GUI_MOUSE, msg);
}
// TODO: Clean this god-function
@@ -285,36 +285,47 @@ int main(int argc, char **argv)
gfx_load_image(&cursor, "/res/cursor.png", 0, 0);
redraw_all();
- event_register(EVENT_MOUSE);
- event_register(EVENT_KEYBOARD);
-
- struct message *msg;
+ struct message msg = { 0 };
+ struct event_keyboard kbd_event = { 0 };
+ struct event_mouse mouse_event = { 0 };
while (1) {
- if (!(msg = msg_receive())) {
+ if (read("/dev/kbd", &kbd_event, 0, sizeof(struct event_keyboard)))
+ handle_keyboard(&kbd_event);
+ /* else if (read("/dev/mouse", &mouse_event, 0, sizeof(struct event_mouse))) */
+ /* handle_mouse(&mouse_event); */
+ /* else if (msg_receive(&msg)) { */
+ /* handle_message(&msg); */
+ /* } */
+ else {
yield();
continue;
}
- switch (msg->type) {
+ //if (!msg_receive(&msg)) {
+ yield();
+ continue;
+ //}
+
+ switch (msg.type) {
case GFX_NEW_CONTEXT: {
- struct context *ctx = msg->data;
+ struct context *ctx = msg.data;
int width = ctx->width;
int height = ctx->height;
int x = ctx->x;
int y = ctx->y;
- ctx->pid = msg->src;
- new_context(ctx, msg->src, x, y, width, height, ctx->flags);
+ ctx->pid = msg.src;
+ new_context(ctx, msg.src, x, y, width, height, ctx->flags);
list_add(contexts, ctx);
if (!(ctx->flags & WF_RELATIVE))
focused = ctx;
redraw_all();
- msg_send(msg->src, GFX_NEW_CONTEXT, ctx);
+ //msg_send(msg.src, GFX_NEW_CONTEXT, ctx);
// Send mouse position
- struct gui_event_mouse *mouse = malloc(sizeof(*msg));
+ struct gui_event_mouse *mouse = malloc(sizeof(msg));
mouse->x = mouse_x - focused->x;
mouse->y = mouse_y - focused->y;
- msg_send(focused->pid, GUI_MOUSE, mouse);
+ //msg_send(focused->pid, GUI_MOUSE, mouse);
break;
}
case GFX_REDRAW:
@@ -323,12 +334,6 @@ int main(int argc, char **argv)
case GFX_REDRAW_FOCUSED:
redraw_focused();
break;
- case EVENT_MOUSE:
- handle_mouse(msg->data);
- break;
- case EVENT_KEYBOARD:
- handle_keyboard(msg->data);
- break;
default:
break;
}
diff --git a/kernel/Makefile b/kernel/Makefile
index 64b5993..492d975 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -14,8 +14,7 @@ COBJS = main.o \
features/proc.o \
features/proc_asm.o \
features/syscall.o \
- features/net.o \
- features/event.o
+ features/net.o
CC = ccache ../cross/opt/bin/i686-elf-gcc
LD = ccache ../cross/opt/bin/i686-elf-ld
OC = ccache ../cross/opt/bin/i686-elf-objcopy
diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c
index f3d0f6e..7dd2416 100644
--- a/kernel/drivers/ide.c
+++ b/kernel/drivers/ide.c
@@ -106,7 +106,7 @@ u8 ata_read_one(u8 *buf, u32 lba, struct device *dev)
return 1;
}
-u32 ata_read(void *buf, u32 lba, u32 sector_count, struct device *dev)
+s32 ata_read(void *buf, u32 lba, u32 sector_count, struct device *dev)
{
u8 *b = buf; // I love bytes, yk
for (u32 i = 0; i < sector_count; i++) {
@@ -147,8 +147,10 @@ void ata_probe(void)
struct vfs *vfs = malloc(sizeof(*vfs));
vfs->type = VFS_EXT2;
vfs->read = ext2_read;
+ vfs->ready = ext2_ready;
vfs->stat = ext2_stat;
dev->vfs = vfs;
+ dev->data = data;
vfs_mount(dev, "/");
}
}
diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c
index 29ff55d..4c5c3b7 100644
--- a/kernel/drivers/interrupts.c
+++ b/kernel/drivers/interrupts.c
@@ -170,11 +170,7 @@ void isr_uninstall_handler(int isr)
void isr_handler(struct regs *r)
{
- // Execute fault handler if exists
- void (*handler)(struct regs * r) = isr_routines[r->int_no];
- if (handler) {
- handler(r);
- } else if (r->int_no <= 32) {
+ if (r->int_no <= 32) {
printf("%s Exception, exiting!\n", isr_exceptions[r->int_no]);
struct proc *proc = proc_current();
if (proc)
@@ -182,6 +178,11 @@ void isr_handler(struct regs *r)
else
__asm__ volatile("cli\nhlt");
proc_yield(r);
+ } else {
+ // Execute fault handler if exists
+ void (*handler)(struct regs * r) = isr_routines[r->int_no];
+ if (handler)
+ handler(r);
}
}
diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c
index ac97d36..0dd7219 100644
--- a/kernel/drivers/keyboard.c
+++ b/kernel/drivers/keyboard.c
@@ -2,13 +2,18 @@
#include <cpu.h>
#include <def.h>
-#include <event.h>
+#include <fs.h>
#include <interrupts.h>
#include <mem.h>
#include <print.h>
+#include <proc.h>
+#include <stack.h>
+#include <str.h>
#include <sys.h>
static struct event_keyboard *event = NULL;
+static struct stack *queue = NULL;
+static u32 dev_id = 0;
static int state = 0;
static int merged = 0;
@@ -34,10 +39,12 @@ void keyboard_handler()
event->magic = KEYBOARD_MAGIC;
event->press = (scancode & 0x80) == 0;
event->scancode = event->press ? scancode : scancode & ~0x80;
- event_trigger(EVENT_KEYBOARD, event);
+ stack_push_bot(queue, event);
state = 0;
merged = 0;
+
+ proc_enable_waiting(dev_id);
}
void keyboard_acknowledge(void)
@@ -53,8 +60,38 @@ void keyboard_rate(void)
outb(0x60, 0x0); // Rate{00000} Delay{00} 0
}
+s32 keyboard_read(void *buf, u32 offset, u32 count, struct device *dev)
+{
+ (void)dev;
+ if (stack_empty(queue))
+ return -1;
+
+ struct event *e = stack_pop(queue);
+ memcpy(buf, (u8 *)e + offset, count);
+ return count;
+}
+
+u8 keyboard_ready(void)
+{
+ return !stack_empty(queue);
+}
+
+void keyboard_reset(void)
+{
+ stack_clear(queue);
+}
+
void keyboard_install(void)
{
//keyboard_rate(); TODO: Fix keyboard rate?
irq_install_handler(1, keyboard_handler);
+
+ queue = stack_new();
+ struct device *dev = malloc(sizeof(*dev));
+ dev->name = strdup("kbd");
+ dev->type = DEV_CHAR;
+ dev->read = keyboard_read;
+ dev->ready = keyboard_ready;
+ device_add(dev);
+ dev_id = dev->id;
}
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
index d58fbfc..2e9ceae 100644
--- a/kernel/drivers/mouse.c
+++ b/kernel/drivers/mouse.c
@@ -2,14 +2,18 @@
#include <boot.h>
#include <cpu.h>
-#include <event.h>
+#include <fs.h>
#include <interrupts.h>
#include <mem.h>
#include <print.h>
+#include <stack.h>
+#include <str.h>
#include <sys.h>
static char mouse_cycle = 0;
static char mouse_byte[3] = { 0 };
+static struct stack *queue = NULL;
+static u32 dev_id = 0;
static struct event_mouse *event = NULL;
@@ -39,7 +43,7 @@ void mouse_handler()
event->but1 = mouse_byte[0] & 1;
event->but2 = (mouse_byte[0] >> 1) & 1;
event->but3 = (mouse_byte[0] >> 2) & 1;
- event_trigger(EVENT_MOUSE, event);
+ stack_push_bot(queue, event);
mouse_cycle = 0;
break;
@@ -48,7 +52,7 @@ void mouse_handler()
}
}
-void mouse_wait(u8 a_type)
+void mouse_serial_wait(u8 a_type)
{
u32 time_out = 100000;
if (a_type == 0) {
@@ -64,96 +68,121 @@ void mouse_wait(u8 a_type)
}
}
-void mouse_write(u8 a_write)
+void mouse_serial_write(u8 a_write)
{
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x64, 0xD4);
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x60, a_write);
}
-u8 mouse_read(void)
+u8 mouse_serial_read(void)
{
- mouse_wait(0);
+ mouse_serial_wait(0);
return inb(0x60);
}
+u8 mouse_ready(void)
+{
+ return !stack_empty(queue);
+}
+
+s32 mouse_read(void *buf, u32 offset, u32 count, struct device *dev)
+{
+ (void)dev;
+ if (stack_empty(queue))
+ return -1;
+
+ struct event *e = stack_pop(queue);
+ memcpy(buf, (u8 *)e + offset, count);
+ return count;
+}
+
void mouse_install(void)
{
u8 status;
// Enable auxiliary mouse device
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x64, 0xA8);
// Enable interrupts
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x64, 0x20);
- mouse_wait(0);
+ mouse_serial_wait(0);
status = (u8)(inb(0x60) | 3);
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x64, 0x60);
- mouse_wait(1);
+ mouse_serial_wait(1);
outb(0x60, status);
// Enable mousewheel
- mouse_write(0xF2);
- mouse_read();
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(200);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(100);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(80);
- mouse_read();
- mouse_write(0xF2);
- mouse_read();
- status = (u8)mouse_read();
+ mouse_serial_write(0xF2);
+ mouse_serial_read();
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(100);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(80);
+ mouse_serial_read();
+ mouse_serial_write(0xF2);
+ mouse_serial_read();
+ status = (u8)mouse_serial_read();
if (status == 3)
printf("Scrollwheel support!\n");
// Activate 4th and 5th mouse buttons
- mouse_write(0xF2);
- mouse_read();
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(200);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(200);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(80);
- mouse_read();
- mouse_write(0xF2);
- mouse_read();
- status = (u8)mouse_read();
+ mouse_serial_write(0xF2);
+ mouse_serial_read();
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(80);
+ mouse_serial_read();
+ mouse_serial_write(0xF2);
+ mouse_serial_read();
+ status = (u8)mouse_serial_read();
if (status == 4)
printf("4th and 5th mouse button support!\n");
/* TODO: Fix mouse laggyness
- mouse_write(0xE8);
- mouse_read();
- mouse_write(0x03);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(200);
- mouse_read(); */
+ mouse_serial_write(0xE8);
+ mouse_serial_read();
+ mouse_serial_write(0x03);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read(); */
// Enable mouse
- mouse_write(0xF4);
- mouse_read();
+ mouse_serial_write(0xF4);
+ mouse_serial_read();
// Setup the mouse handler
irq_install_handler(12, mouse_handler);
+
+ queue = stack_new();
+ struct device *dev = malloc(sizeof(*dev));
+ dev->name = strdup("mouse");
+ dev->type = DEV_CHAR;
+ dev->read = mouse_read;
+ dev->ready = mouse_ready;
+ device_add(dev);
+ dev_id = dev->id;
}
diff --git a/kernel/features/event.c b/kernel/features/event.c
deleted file mode 100644
index c9bd3a4..0000000
--- a/kernel/features/event.c
+++ /dev/null
@@ -1,61 +0,0 @@
-// MIT License, Copyright (c) 2020 Marvin Borner
-
-#include <assert.h>
-#include <def.h>
-#include <event.h>
-#include <list.h>
-#include <mem.h>
-#include <proc.h>
-#include <sys.h>
-
-static struct list *event_table[] = { [EVENT_KEYBOARD] = NULL, [EVENT_MOUSE] = NULL };
-
-u32 event_register(u32 id, struct proc *proc)
-{
- assert(id < sizeof(event_table) / sizeof(*event_table));
-
- if (event_table[id] == NULL)
- event_table[id] = (struct list *)list_new();
-
- struct event_descriptor *desc = malloc(sizeof(*desc));
- desc->id = id;
- desc->proc = proc;
-
- list_add(event_table[id], (void *)desc);
- return 0;
-}
-
-void event_unregister(u32 id, struct proc *proc)
-{
- assert(id < sizeof(event_table) / sizeof(*event_table));
-
- struct event_descriptor desc;
- desc.id = id;
- desc.proc = proc;
-
- struct node *iterator = event_table[id]->head;
- while (iterator != NULL) {
- struct event_descriptor *desc_comp = iterator->data;
- if (desc_comp->id == desc.id && desc_comp->proc == desc.proc)
- list_remove(event_table[id], iterator);
- iterator = iterator->next;
- }
-}
-
-u32 event_trigger(u32 id, void *data)
-{
- assert(id < sizeof(event_table) / sizeof(*event_table));
-
- if (!event_table[id] || !event_table[id]->head) {
- printf("Event %d not mapped!\n", id);
- return 1;
- }
-
- struct node *iterator = event_table[id]->head;
- while (iterator != NULL) {
- proc_send(kernel_proc, ((struct event_descriptor *)iterator->data)->proc, id, data);
- iterator = iterator->next;
- }
-
- return 0;
-}
diff --git a/kernel/features/fs.c b/kernel/features/fs.c
index 14e6a9c..b59eb03 100644
--- a/kernel/features/fs.c
+++ b/kernel/features/fs.c
@@ -24,7 +24,7 @@ char *vfs_normalize_path(const char *path)
return fixed;
}
-u32 vfs_mounted(struct device *dev, const char *path)
+u8 vfs_mounted(struct device *dev, const char *path)
{
struct node *iterator = mount_points->head;
while (iterator) {
@@ -70,6 +70,8 @@ struct device *vfs_find_dev(const char *path)
{
assert(path[0] == '/');
struct mount_info *m = vfs_find_mount_info(path);
+ if (m->dev->vfs->type == VFS_DEVFS) // TODO: ?
+ return device_get_by_name(path + strlen(m->path) + 1);
return m && m->dev ? m->dev : NULL;
}
@@ -100,11 +102,11 @@ void vfs_list_mounts()
}
}
-u32 vfs_mount(struct device *dev, const char *path)
+s32 vfs_mount(struct device *dev, const char *path)
{
// TODO: Check if already mounted
if (!dev || !dev->id || vfs_mounted(dev, path))
- return 0;
+ return -1;
char *fixed = vfs_normalize_path(path);
@@ -113,14 +115,20 @@ u32 vfs_mount(struct device *dev, const char *path)
m->dev = dev;
list_add(mount_points, m);
- return 1;
+ return 0;
}
-u32 vfs_read(const char *path, void *buf, u32 offset, u32 count)
+s32 vfs_read(const char *path, void *buf, u32 offset, u32 count)
{
- if (count == 0 || offset > count)
+ if (!count)
return 0;
+ if (offset > count)
+ return -1;
+
+ while (*path == ' ')
+ path++;
+
struct mount_info *m = vfs_find_mount_info(path);
assert(m && m->dev && m->dev->vfs && m->dev->vfs->read);
@@ -128,22 +136,58 @@ u32 vfs_read(const char *path, void *buf, u32 offset, u32 count)
if (len > 1)
path += len;
- struct device *dev = m->dev;
- return dev->vfs->read(path, buf, offset, count, dev);
+ return m->dev->vfs->read(path, buf, offset, count, m->dev);
+}
+
+s32 vfs_write(const char *path, void *buf, u32 offset, u32 count)
+{
+ if (!count)
+ return 0;
+
+ if (offset > count)
+ return -1;
+
+ while (*path == ' ')
+ path++;
+
+ struct mount_info *m = vfs_find_mount_info(path);
+ assert(m && m->dev && m->dev->vfs && m->dev->vfs->write);
+
+ u32 len = strlen(m->path);
+ if (len > 1)
+ path += len;
+
+ return m->dev->vfs->write(path, buf, offset, count, m->dev);
}
-u32 vfs_write(const char *path, void *buf, u32 offset, u32 count)
+s32 vfs_stat(const char *path, struct stat *buf)
{
- struct device *dev = vfs_find_dev(path);
- assert(dev && dev->vfs && dev->vfs->write);
- return dev->vfs->write(path, buf, offset, count, dev);
+ while (*path == ' ')
+ path++;
+
+ struct mount_info *m = vfs_find_mount_info(path);
+ assert(m && m->dev && m->dev->vfs && m->dev->vfs->stat);
+
+ u32 len = strlen(m->path);
+ if (len > 1)
+ path += len;
+
+ return m->dev->vfs->stat(path, buf, m->dev);
}
-u32 vfs_stat(const char *path, struct stat *buf)
+u8 vfs_ready(const char *path)
{
- struct device *dev = vfs_find_dev(path);
- assert(dev && dev->vfs && dev->vfs->stat);
- return dev->vfs->stat(path, buf, dev);
+ while (*path == ' ')
+ path++;
+
+ struct mount_info *m = vfs_find_mount_info(path);
+ assert(m && m->dev && m->dev->vfs && m->dev->vfs->ready);
+
+ u32 len = strlen(m->path);
+ if (len > 1)
+ path += len;
+
+ return m->dev->vfs->ready(path, m->dev);
}
void vfs_install(void)
@@ -163,7 +207,7 @@ void device_add(struct device *dev)
list_add(devices, dev);
}
-struct device *device_get(u32 id)
+struct device *device_get_by_id(u32 id)
{
struct node *iterator = devices->head;
while (iterator) {
@@ -174,25 +218,46 @@ struct device *device_get(u32 id)
return NULL;
}
-u32 devfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
+struct device *device_get_by_name(const char *name)
+{
+ struct node *iterator = devices->head;
+ while (iterator) {
+ if (!strcmp(((struct device *)iterator->data)->name, name))
+ return iterator->data;
+ iterator = iterator->next;
+ }
+ return NULL;
+}
+
+s32 devfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
+{
+ struct device *target = device_get_by_name(path + 1);
+ if (!target || !target->read)
+ return 0;
+ return target->read(buf, offset, count, dev);
+}
+
+u8 devfs_ready(const char *path, struct device *dev)
{
- assert(dev && dev->read);
- printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev);
- return dev->read(buf, offset, count, dev);
+ (void)dev;
+
+ struct device *target = device_get_by_name(path + 1);
+ if (!target || !target->ready)
+ return 0;
+ return target->ready();
}
void device_install(void)
{
devices = list_new();
- struct vfs *vfs;
- struct device *dev;
-
- vfs = malloc(sizeof(*vfs));
+ struct vfs *vfs = malloc(sizeof(*vfs));
vfs->type = VFS_DEVFS;
vfs->read = devfs_read;
- dev = malloc(sizeof(*dev));
+ vfs->ready = devfs_ready;
+ struct device *dev = malloc(sizeof(*dev));
dev->name = "dev";
+ dev->type = DEV_CHAR;
dev->vfs = vfs;
device_add(dev);
vfs_mount(dev, "/dev/");
@@ -204,6 +269,7 @@ void device_install(void)
* EXT2
*/
+// TODO: Remove malloc from buffer_read (attempt in #56cd63f199)
void *buffer_read(u32 block, struct device *dev)
{
void *buf = malloc(BLOCK_SIZE);
@@ -215,8 +281,7 @@ struct ext2_superblock *get_superblock(struct device *dev)
{
struct ext2_superblock *sb = buffer_read(EXT2_SUPER, dev);
- if (sb->magic != EXT2_MAGIC)
- return NULL;
+ assert(sb->magic == EXT2_MAGIC);
return sb;
}
@@ -237,31 +302,38 @@ struct ext2_inode *get_inode(u32 i, struct device *dev)
u32 block = (index * EXT2_INODE_SIZE) / BLOCK_SIZE;
b += block_group;
- u32 *data = buffer_read(b->inode_table + block, dev);
+ u32 *buf = buffer_read(b->inode_table + block, dev);
struct ext2_inode *in =
- (struct ext2_inode *)((u32)data +
+ (struct ext2_inode *)((u32)buf +
(index % (BLOCK_SIZE / EXT2_INODE_SIZE)) * EXT2_INODE_SIZE);
+
+ free(buf);
+ free(s);
+ free(b - block_group);
+
return in;
}
u32 read_indirect(u32 indirect, u32 block_num, struct device *dev)
{
char *data = buffer_read(indirect, dev);
- return *(u32 *)((u32)data + block_num * sizeof(u32));
+ u32 ind = *(u32 *)((u32)data + block_num * sizeof(u32));
+ free(data);
+ return ind;
}
-u32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct device *dev)
+s32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct device *dev)
{
// TODO: Support read offset
(void)offset;
if (!in || !buf)
- return 0;
+ return -1;
u32 num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE);
if (!num_blocks)
- return 0;
+ return -1;
// TODO: memcpy block chunks until count is copied
while (BLOCK_SIZE * num_blocks > count)
@@ -269,28 +341,25 @@ u32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct d
u32 indirect = 0;
u32 blocknum = 0;
- char *data = 0;
// TODO: Support triply indirect pointers
// TODO: This can be heavily optimized by saving the indirect block lists
for (u32 i = 0; i < num_blocks; i++) {
if (i < 12) {
blocknum = in->block[i];
- data = buffer_read(blocknum, dev);
- memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE);
} else if (i < BLOCK_COUNT + 12) {
indirect = in->block[12];
blocknum = read_indirect(indirect, i - 12, dev);
- data = buffer_read(blocknum, dev);
- memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE);
} else {
indirect = in->block[13];
blocknum = read_indirect(indirect, (i - (BLOCK_COUNT + 12)) / BLOCK_COUNT,
dev);
blocknum = read_indirect(blocknum, (i - (BLOCK_COUNT + 12)) % BLOCK_COUNT,
dev);
- data = buffer_read(blocknum, dev);
- memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE);
}
+
+ char *data = buffer_read(blocknum, dev);
+ memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE);
+ free(data);
/* printf("Loaded %d of %d\n", i + 1, num_blocks); */
}
@@ -310,6 +379,7 @@ u32 find_inode(const char *name, u32 dir_inode, struct device *dev)
for (u32 q = 0; q < i->blocks / 2; q++) {
char *data = buffer_read(i->block[q], dev);
memcpy((u32 *)((u32)buf + q * BLOCK_SIZE), data, BLOCK_SIZE);
+ free(data);
}
struct ext2_dirent *d = (struct ext2_dirent *)buf;
@@ -341,7 +411,7 @@ struct ext2_inode *find_inode_by_path(const char *path, struct device *dev)
path_cp++;
u32 current_inode = EXT2_ROOT;
- int i = 0;
+ u32 i = 0;
while (1) {
for (i = 0; path_cp[i] != '/' && path_cp[i] != '\0'; i++)
;
@@ -369,23 +439,23 @@ struct ext2_inode *find_inode_by_path(const char *path, struct device *dev)
return get_inode(inode, dev);
}
-u32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
+s32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
{
struct ext2_inode *in = find_inode_by_path(path, dev);
if (in)
return read_inode(in, buf, offset, count, dev);
else
- return 0;
+ return -1;
}
-u32 ext2_stat(const char *path, struct stat *buf, struct device *dev)
+s32 ext2_stat(const char *path, struct stat *buf, struct device *dev)
{
if (!buf)
- return 1;
+ return -1;
struct ext2_inode *in = find_inode_by_path(path, dev);
if (!in)
- return 1;
+ return -1;
u32 num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE);
u32 sz = BLOCK_SIZE * num_blocks;
@@ -395,3 +465,10 @@ u32 ext2_stat(const char *path, struct stat *buf, struct device *dev)
return 0;
}
+
+u8 ext2_ready(const char *path, struct device *dev)
+{
+ (void)path;
+ (void)dev;
+ return 1;
+}
diff --git a/kernel/features/load.c b/kernel/features/load.c
index 1eb34d3..3e1ea8e 100644
--- a/kernel/features/load.c
+++ b/kernel/features/load.c
@@ -1,28 +1,30 @@
// MIT License, Copyright (c) 2020 Marvin Borner
-#include <assert.h>
-#include <cpu.h>
-#include <def.h>
#include <fs.h>
#include <load.h>
#include <mem.h>
-#include <proc.h>
#include <str.h>
+void proc_load(struct proc *proc, void *data)
+{
+ u32 stack = (u32)malloc(0x2000) + 0x1000;
+
+ proc->regs.ebp = (u32)stack;
+ proc->regs.useresp = (u32)stack;
+ proc->regs.eip = (u32)data;
+}
+
int bin_load(char *path, struct proc *proc)
{
// TODO: Remove hardcoded filesize
struct stat s = { 0 };
vfs_stat(path, &s);
char *data = malloc(s.size);
- vfs_read(path, data, 0, s.size);
-
- u32 stack = (u32)malloc(0x2000) + 0x1000;
+ if (!vfs_read(path, data, 0, s.size))
+ return 1;
- proc->regs.ebp = (u32)stack;
- proc->regs.useresp = (u32)stack;
- proc->regs.eip = (u32)data;
- strcpy(proc->name, path + 1);
+ strcpy(proc->name, path);
+ proc_load(proc, data);
- return data ? 0 : 1;
+ return 0;
}
diff --git a/kernel/features/proc.c b/kernel/features/proc.c
index d76312c..bec48fa 100644
--- a/kernel/features/proc.c
+++ b/kernel/features/proc.c
@@ -3,12 +3,12 @@
#include <assert.h>
#include <boot.h>
#include <cpu.h>
-#include <interrupts.h>
-#include <list.h>
+#include <fs.h>
#include <load.h>
#include <mem.h>
#include <print.h>
#include <proc.h>
+#include <stack.h>
#include <str.h>
#include <timer.h>
@@ -16,6 +16,7 @@ u32 current_pid = 0;
u32 quantum = 0;
struct proc *priority_proc;
struct list *proc_list;
+struct node *idle_proc;
struct node *current;
// TODO: Use less memcpy and only copy relevant registers
@@ -44,8 +45,7 @@ void scheduler(struct regs *regs)
} else if (((struct proc *)proc_list->head->data)->state == PROC_RUNNING) {
current = proc_list->head;
} else {
- print("TODO: All processes are sleeping!\n"); // TODO!
- /* loop(); */
+ current = idle_proc;
}
memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs));
@@ -63,6 +63,12 @@ void scheduler(struct regs *regs)
/* printf("{%d}", ((struct proc *)current->data)->pid); */
}
+void kernel_idle()
+{
+ while (1)
+ ;
+}
+
void proc_print(void)
{
struct node *node = proc_list->head;
@@ -82,33 +88,6 @@ struct proc *proc_current(void)
return current && current->data ? current->data : NULL;
}
-void proc_send(struct proc *src, struct proc *dest, u32 type, void *data)
-{
- // TODO: Use unique key instead of pid for IPC
- if (!src || !dest)
- return;
- struct proc_message *msg = malloc(sizeof(*msg));
- msg->src = src;
- msg->dest = dest;
- msg->msg = malloc(sizeof(struct message));
- msg->msg->src = (int)src->pid;
- msg->msg->type = (int)type;
- msg->msg->data = data;
- list_add(dest->messages, msg);
- priority_proc = dest;
-}
-
-struct proc_message *proc_receive(struct proc *proc)
-{
- if (proc->messages && proc->messages->head) {
- struct proc_message *msg = proc->messages->head->data;
- list_remove(proc->messages, proc->messages->head);
- return msg;
- } else {
- return NULL;
- }
-}
-
struct proc *proc_from_pid(u32 pid)
{
struct node *iterator = proc_list->head;
@@ -120,13 +99,18 @@ struct proc *proc_from_pid(u32 pid)
return NULL;
}
+void proc_clear_quantum()
+{
+ quantum = 0;
+}
+
void proc_exit(struct proc *proc, int status)
{
assert(proc);
int res = 0;
struct node *iterator = proc_list->head;
- while (iterator != NULL) {
+ while (iterator) {
if (iterator->data == proc) {
res = 1;
list_remove(proc_list, iterator);
@@ -141,20 +125,38 @@ void proc_exit(struct proc *proc, int status)
if (res)
printf("Process %s exited with status %d\n", proc->name, status);
- quantum = 0; // TODO: Add quantum to each process struct?
+ proc_clear_quantum(); // TODO: Add quantum to each process struct?
+ sti();
+ hlt();
}
void proc_yield(struct regs *r)
{
- quantum = 0;
+ proc_clear_quantum();
scheduler(r);
}
+void proc_enable_waiting(u32 dev_id)
+{
+ struct node *iterator = proc_list->head;
+ while (iterator) {
+ struct proc *p = iterator->data;
+ struct proc_wait *w = &p->wait;
+ if (p && w && w->id == dev_id) {
+ struct regs *r = &p->regs;
+ r->eax = (u32)w->func((char *)r->ebx, (void *)r->ecx, r->edx, r->esi);
+ memset(&p->wait, 0, sizeof(p->wait));
+ p->state = PROC_RUNNING;
+ }
+ iterator = iterator->next;
+ }
+}
+
struct proc *proc_make(void)
{
struct proc *proc = malloc(sizeof(*proc));
proc->pid = current_pid++;
- proc->messages = list_new();
+ proc->messages = stack_new();
proc->state = PROC_RUNNING;
if (current)
@@ -163,6 +165,94 @@ struct proc *proc_make(void)
return proc;
}
+s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
+{
+ while (*path == '/')
+ path++;
+
+ int pid = 0;
+ while (path[0] >= '0' && path[0] <= '9') {
+ pid = pid * 10 + (path[0] - '0');
+ path++;
+ }
+
+ if (!pid && !memcmp(path, "self/", 5)) {
+ pid = proc_current()->pid;
+ path += 4;
+ }
+
+ if (pid) {
+ struct proc *p = proc_from_pid(pid);
+ if (!p || path[0] != '/')
+ return -1;
+
+ path++;
+ if (!memcmp(path, "msg", 4)) {
+ stack_push_bot(p->messages, buf);
+ return count;
+ }
+ }
+
+ printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev);
+ return -1;
+}
+
+s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev)
+{
+ (void)dev;
+
+ while (*path == '/')
+ path++;
+
+ int pid = 0;
+ while (path[0] >= '0' && path[0] <= '9') {
+ pid = pid * 10 + (path[0] - '0');
+ path++;
+ }
+
+ if (!pid && !memcmp(path, "self/", 5)) {
+ pid = proc_current()->pid;
+ path += 4;
+ }
+
+ if (pid) {
+ struct proc *p = proc_from_pid(pid);
+ if (!p || path[0] != '/')
+ return -1;
+
+ path++;
+ if (!memcmp(path, "pid", 4)) {
+ //memcpy(buf, ((u8 *)p->pid) + offset, count);
+ *(u32 *)buf = p->pid;
+ return count;
+ } else if (!memcmp(path, "name", 5)) {
+ memcpy(buf, p->name + offset, count);
+ return count;
+ } else if (!memcmp(path, "status", 7)) {
+ const char *status = p->state == PROC_RUNNING ? "running" : "sleeping";
+ memcpy(buf, status + offset, count);
+ return count;
+ } else if (!memcmp(path, "msg", 4)) {
+ if (stack_empty(p->messages)) {
+ return 0;
+ } else {
+ u8 *msg = stack_pop(p->messages);
+ memcpy(buf, msg + offset, count);
+ return count;
+ }
+ }
+ }
+
+ return -1;
+}
+
+u8 procfs_ready(const char *path, struct device *dev)
+{
+ (void)path;
+ (void)dev;
+ return 1;
+}
+
extern void proc_jump_userspace(void);
u32 _esp, _eip;
@@ -175,7 +265,27 @@ void proc_init(void)
scheduler_enable();
proc_list = list_new();
- kernel_proc = proc_make();
+ // Procfs
+ struct vfs *vfs = malloc(sizeof(*vfs));
+ vfs->type = VFS_PROCFS;
+ vfs->read = procfs_read;
+ vfs->write = procfs_write;
+ vfs->ready = procfs_ready;
+ vfs->data = NULL;
+ struct device *dev = malloc(sizeof(*dev));
+ dev->name = "proc";
+ dev->type = DEV_CHAR;
+ dev->vfs = vfs;
+ device_add(dev);
+ vfs_mount(dev, "/proc/");
+
+ // Idle proc
+ struct proc *kernel_proc = proc_make();
+ void (*func)() = kernel_idle;
+ proc_load(kernel_proc, *(void **)&func);
+ strcpy(kernel_proc->name, "idle");
+ kernel_proc->state = PROC_SLEEPING;
+ idle_proc = list_add(proc_list, kernel_proc);
struct node *new = list_add(proc_list, proc_make());
bin_load((char *)"/bin/init", new->data);
diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c
index e2df79a..d980317 100644
--- a/kernel/features/syscall.c
+++ b/kernel/features/syscall.c
@@ -1,7 +1,6 @@
// MIT License, Copyright (c) 2020 Marvin Borner
#include <cpu.h>
-#include <event.h>
#include <fs.h>
#include <interrupts.h>
#include <load.h>
@@ -38,7 +37,18 @@ void syscall_handler(struct regs *r)
break;
}
case SYS_READ: {
- r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi);
+ if (vfs_ready((char *)r->ebx)) {
+ r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi);
+ } else {
+ struct proc *p = proc_current();
+ p->state = PROC_SLEEPING;
+ p->wait.id = vfs_find_dev((char *)r->ebx)->id;
+ p->wait.func = vfs_read;
+ proc_yield(r);
+ sti();
+ while (1)
+ hlt();
+ }
break;
}
case SYS_WRITE: {
@@ -74,28 +84,6 @@ void syscall_handler(struct regs *r)
r->eax = timer_get();
break;
}
- case SYS_REGISTER: {
- event_register(r->ebx, proc_current());
- break;
- }
- case SYS_UNREGISTER: {
- event_unregister(r->ebx, proc_current());
- break;
- }
- case SYS_SEND: {
- proc_send(proc_current(), proc_from_pid(r->ebx), r->ecx, (void *)r->edx);
- proc_yield(r);
- break;
- }
- case SYS_RECEIVE: {
- struct proc_message *msg = proc_receive(proc_current());
- r->eax = (u32)(msg ? msg->msg : NULL);
- break;
- }
- case SYS_GETPID: {
- r->eax = proc_current()->pid;
- break;
- }
case SYS_NET_OPEN: {
r->eax = (int)net_open(r->ebx);
break;
diff --git a/kernel/inc/event.h b/kernel/inc/event.h
deleted file mode 100644
index 59a0df1..0000000
--- a/kernel/inc/event.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// MIT License, Copyright (c) 2020 Marvin Borner
-
-#ifndef EVENT_H
-#define EVENT_H
-
-#include <def.h>
-#include <proc.h>
-#include <sys.h>
-
-struct event_descriptor {
- u32 id;
- struct proc *proc;
-};
-
-u32 event_register(u32 id, struct proc *proc);
-void event_unregister(u32 id, struct proc *proc);
-u32 event_trigger(u32 id, void *data);
-
-#endif
diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h
index ff14361..64f3970 100644
--- a/kernel/inc/fs.h
+++ b/kernel/inc/fs.h
@@ -18,8 +18,9 @@ struct device {
enum dev_type type;
struct vfs *vfs;
void *data;
- u32 (*read)(void *buf, u32 offset, u32 count, struct device *dev);
- u32 (*write)(void *buf, u32 offset, u32 count, struct device *dev);
+ s32 (*read)(void *buf, u32 offset, u32 count, struct device *dev);
+ s32 (*write)(void *buf, u32 offset, u32 count, struct device *dev);
+ u8 (*ready)();
};
void device_install(void);
@@ -35,9 +36,11 @@ enum vfs_type { VFS_DEVFS, VFS_TMPFS, VFS_PROCFS, VFS_EXT2 };
struct vfs {
enum vfs_type type;
int flags;
- u32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
- u32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
- u32 (*stat)(const char *path, struct stat *buf, struct device *dev);
+ void *data;
+ s32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
+ s32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
+ s32 (*stat)(const char *path, struct stat *buf, struct device *dev);
+ u8 (*ready)(const char *path, struct device *dev);
};
struct mount_info {
@@ -47,12 +50,17 @@ struct mount_info {
void vfs_install(void);
-u32 vfs_mounted(struct device *dev, const char *path);
-u32 vfs_mount(struct device *dev, const char *path);
+u8 vfs_mounted(struct device *dev, const char *path);
+s32 vfs_mount(struct device *dev, const char *path);
+
+struct device *vfs_find_dev(const char *path);
+
+s32 vfs_read(const char *path, void *buf, u32 offset, u32 count);
+s32 vfs_write(const char *path, void *buf, u32 offset, u32 count);
+s32 vfs_stat(const char *path, struct stat *buf);
+u8 vfs_ready(const char *path);
-u32 vfs_read(const char *path, void *buf, u32 offset, u32 count);
-u32 vfs_write(const char *path, void *buf, u32 offset, u32 count);
-u32 vfs_stat(const char *path, struct stat *buf);
+struct device *device_get_by_name(const char *name);
/**
* EXT2
@@ -145,7 +153,8 @@ struct ext2_file {
u32 curr_block_pos;
};
-u32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
-u32 ext2_stat(const char *path, struct stat *buf, struct device *dev);
+s32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
+s32 ext2_stat(const char *path, struct stat *buf, struct device *dev);
+u8 ext2_ready(const char *path, struct device *dev);
#endif
diff --git a/kernel/inc/keyboard.h b/kernel/inc/keyboard.h
index 32168f4..22120e5 100644
--- a/kernel/inc/keyboard.h
+++ b/kernel/inc/keyboard.h
@@ -4,5 +4,6 @@
#define KEYBOARD_H
void keyboard_install(void);
+void keyboard_reset(void);
#endif
diff --git a/kernel/inc/load.h b/kernel/inc/load.h
index 43c941c..422a28c 100644
--- a/kernel/inc/load.h
+++ b/kernel/inc/load.h
@@ -5,60 +5,7 @@
#include <proc.h>
-#define ELF_MAG 0x7F // 0
-#define ELF_32 (1) // 4: 32-bit Architecture
-#define ELF_LITTLE (1) // 5: Little Endian
-#define ELF_CURRENT (1) // 6: ELF Current Version
-#define ELF_386 (3) // header->machine x86 machine type
-
-#define ET_NONE 0 // Unkown type
-#define ET_REL 1 // Relocatable file
-#define ET_EXEC 2 // Executable file
-
-#define PT_LOAD 1
-
-struct elf_header {
- u8 ident[16];
- u16 type;
- u16 machine;
- u32 version;
- u32 entry;
- u32 phoff;
- u32 shoff;
- u32 flags;
- u16 ehsize;
- u16 phentsize;
- u16 phnum;
- u16 shentsize;
- u16 shnum;
- u16 shstrndx;
-};
-
-struct elf_section_header {
- u32 name;
- u32 type;
- u32 flags;
- u32 addr;
- u32 offset;
- u32 size;
- u32 link;
- u32 info;
- u32 addralign;
- u32 entsize;
-};
-
-struct elf_program_header {
- u32 type;
- u32 offset;
- u32 vaddr;
- u32 paddr;
- u32 filesz;
- u32 memsz;
- u32 flags;
- u32 align;
-};
-
+void proc_load(struct proc *proc, void *data);
int bin_load(char *path, struct proc *proc);
-void elf_load(char *path, struct proc *proc);
#endif
diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h
index 5fc217c..6be7da3 100644
--- a/kernel/inc/proc.h
+++ b/kernel/inc/proc.h
@@ -4,12 +4,12 @@
#define PROC_H
#include <def.h>
-#include <event.h>
#include <interrupts.h>
#include <list.h>
+#include <stack.h>
#include <sys.h>
-#define PROC_QUANTUM 100 // Milliseconds or something // TODO
+#define PROC_QUANTUM 42 // Milliseconds or something // TODO
#define EFLAGS_ALWAYS 0x2 // Always one
#define EFLAGS_INTERRUPTS 0x200 // Enable interrupts
@@ -19,32 +19,29 @@
enum proc_state { PROC_RUNNING, PROC_SLEEPING };
+struct proc_wait {
+ u32 id; // dev_id
+ s32 (*func)();
+};
+
struct proc {
u32 pid;
char name[32];
struct regs regs;
- struct regs regs_backup;
+ struct proc_wait wait; // dev_id
enum proc_state state;
- struct list *messages;
+ struct stack *messages;
};
-struct proc_message {
- struct proc *src;
- struct proc *dest;
- struct message *msg;
-};
-
-struct proc *kernel_proc;
-
void scheduler(struct regs *regs);
void proc_init(void);
void proc_print(void);
struct proc *proc_current(void);
-void proc_send(struct proc *src, struct proc *dest, u32 type, void *data);
-struct proc_message *proc_receive(struct proc *proc);
struct proc *proc_from_pid(u32 pid);
void proc_exit(struct proc *proc, int status);
void proc_yield(struct regs *r);
+void proc_clear_quantum();
+void proc_enable_waiting(u32 dev_id);
struct proc *proc_make(void);
#endif
diff --git a/kernel/main.c b/kernel/main.c
index 563cae7..7466f5d 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -40,6 +40,7 @@ void kernel_main(struct vid_info *vid_info)
// Enable drivers
sti();
+ keyboard_reset();
syscall_init();
proc_init();
diff --git a/libc/Makefile b/libc/Makefile
index 1a8e0f0..a3d1300 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -10,6 +10,7 @@ COBJS = str.o \
cpu.o \
sys.o \
list.o \
+ stack.o \
random.o
CC = ccache ../cross/opt/bin/i686-elf-gcc
LD = ccache ../cross/opt/bin/i686-elf-ld
diff --git a/libc/inc/assert.h b/libc/inc/assert.h
index 3e45f44..e42fc5a 100644
--- a/libc/inc/assert.h
+++ b/libc/inc/assert.h
@@ -9,7 +9,8 @@
#include <proc.h>
#define assert(exp) \
if (!(exp)) { \
- printf("%s:%d: %s: Assertion '%s' failed\n", __FILE__, __LINE__, __func__, #exp); \
+ printf("%s:%d: %s: Kernel assertion '%s' failed\n", __FILE__, __LINE__, __func__, \
+ #exp); \
struct proc *assert_proc = proc_current(); \
if (assert_proc) \
proc_exit(assert_proc, 1); \
diff --git a/libc/inc/mem.h b/libc/inc/mem.h
index 15505fd..e35ee62 100644
--- a/libc/inc/mem.h
+++ b/libc/inc/mem.h
@@ -5,16 +5,21 @@
#include <def.h>
-// Huh
+int malloc_allocated;
+
+void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp);
+void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp);
+#define malloc(size) malloc_debug(size, __FILE__, __LINE__, __func__, #size)
+#define free(ptr) free_debug(ptr, __FILE__, __LINE__, __func__, #ptr)
+
+/* void *_malloc(u32 size); */
+/* void _free(void *ptr); */
+/* #define malloc(size) _malloc(size) */
+/* #define free(ptr) _free(ptr) */
+
#ifdef kernel
-#define HEAP_SIZE 0x10000
-#define HEAP_MAGIC 0x42
void heap_init(u32 start);
-void *malloc(u32 size);
-void free(void *ptr);
#elif defined(userspace)
-void *malloc(u32 size);
-void free(void *ptr);
#else
#error "No lib target specified. Please use -Dkernel or -Duserspace"
#endif
@@ -23,5 +28,6 @@ void *memcpy(void *dest, const void *src, u32 n);
void *memset(void *dest, int val, u32 n);
void *memchr(void *src, int c, u32 n);
int memcmp(const void *s1, const void *s2, u32 n);
+int mememp(const u8 *buf, u32 n);
#endif
diff --git a/libc/inc/stack.h b/libc/inc/stack.h
new file mode 100644
index 0000000..16725f8
--- /dev/null
+++ b/libc/inc/stack.h
@@ -0,0 +1,28 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#ifndef STACK_H
+#define STACK_H
+
+#include <def.h>
+
+struct stack_node {
+ void *data;
+ int nonce;
+ struct stack_node *next;
+ struct stack_node *prev;
+};
+
+struct stack {
+ struct stack_node *tail;
+};
+
+struct stack *stack_new();
+void stack_destroy(struct stack *stack);
+u32 stack_empty(struct stack *stack);
+u32 stack_push_bot(struct stack *stack, void *data);
+u32 stack_push(struct stack *stack, void *data);
+void *stack_pop(struct stack *stack);
+void *stack_peek(struct stack *stack);
+void stack_clear(struct stack *stack);
+
+#endif
diff --git a/libc/inc/sys.h b/libc/inc/sys.h
index 3145432..14f83dd 100644
--- a/libc/inc/sys.h
+++ b/libc/inc/sys.h
@@ -20,11 +20,6 @@ enum sys {
SYS_EXIT, // Exit current process // TODO: Free all memory of process
SYS_YIELD, // Switch to next process
SYS_TIME, // Get kernel time
- SYS_REGISTER, // Register for event
- SYS_UNREGISTER, // Unregister event
- SYS_SEND, // Send message to process
- SYS_RECEIVE, // Receive message (non-blocking/sync)
- SYS_GETPID, // Get the process ID
SYS_NET_OPEN, // Open network socket
SYS_NET_CLOSE, // Close network socket
SYS_NET_CONNECT, // Connect to destination
@@ -94,22 +89,33 @@ int sysv(enum sys num, ...);
#define yield() (int)sys0(SYS_YIELD)
#define time() (u32) sys0(SYS_TIME)
-#define event_register(id) sys1(SYS_REGISTER, (int)(id))
-#define event_unregister(id) sys1(SYS_UNREGISTER, (int)(id))
+static inline u32 getpid()
+{
+ u32 buf = 0;
+ read("/proc/self/pid", &buf, 0, sizeof(buf));
+ return buf;
+}
-#define msg_send(pid, type, msg) sys3(SYS_SEND, (int)(pid), (int)(type), (int)(msg))
-#define msg_receive() (struct message *)sys0(SYS_RECEIVE)
-#define getpid() (int)sys0(SYS_GETPID)
-static inline struct message *msg_receive_loop()
+// Hacky one-digit solution - TODO!
+#include <mem.h>
+#include <str.h>
+static inline u32 pidof(const char *name)
{
- struct message *msg;
- while (!(msg = msg_receive()))
- yield();
- return msg;
+ u32 curr = 1;
+ char buf[32] = { 0 };
+ char *path = (char *)"/proc/1/name"; // AAH
+ while (read(path, buf, 0, 32)) {
+ if (!strcmp(name, buf))
+ return curr;
+
+ curr++;
+ path[7]++;
+ }
+
+ return 0;
}
// Simple read wrapper
-#include <mem.h>
static inline void *sread(const char *path)
{
struct stat s = { 0 };
diff --git a/libc/mem.c b/libc/mem.c
index dc4e0e6..aab68b2 100644
--- a/libc/mem.c
+++ b/libc/mem.c
@@ -1,5 +1,6 @@
// MIT License, Copyright (c) 2020 Marvin Borner
+#include <assert.h>
#include <def.h>
#include <mem.h>
#include <sys.h>
@@ -68,126 +69,318 @@ int memcmp(const void *s1, const void *s2, u32 n)
return 0;
}
-#define ALIGNMENT 16ul
-#define ALIGN_TYPE char
-#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
+int mememp(const u8 *buf, u32 n)
+{
+ return buf[0] == 0 && !memcmp(buf, buf + 1, n - 1);
+}
-#define ALIGN(ptr) \
- if (ALIGNMENT > 1) { \
- u32 diff; \
- ptr = (void *)((u32)ptr + ALIGN_INFO); \
- diff = (u32)ptr & (ALIGNMENT - 1); \
- if (diff != 0) { \
- diff = ALIGNMENT - diff; \
- ptr = (void *)((u32)ptr + diff); \
- } \
- *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
- }
+/**
+ * Heap allocator
+ */
+
+#ifdef kernel
-#define UNALIGN(ptr) \
- if (ALIGNMENT > 1) { \
- u32 diff = *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)); \
- if (diff < (ALIGNMENT + ALIGN_INFO)) { \
- ptr = (void *)((u32)ptr - diff); \
- } \
+int malloc_allocated = 0;
+
+#define HEAP_MAGIC 0x42424242
+#define HEAP_INIT_SIZE 0xff000000
+#define HEAP_MIN_SIZE HEAP_INIT_SIZE
+#define MIN_ALLOC_SZ 4
+#define BIN_COUNT 9
+#define BIN_MAX_IDX (BIN_COUNT - 1)
+#define OVERHEAD (sizeof(struct h_footer) + sizeof(struct h_node))
+/* #define MIN_WILDERNESS 0x2000 */
+/* #define MAX_WILDERNESS 0x1000000 */
+
+struct h_node {
+ u32 magic;
+ u32 hole;
+ u32 size;
+ struct h_node *next;
+ struct h_node *prev;
+};
+
+struct h_footer {
+ struct h_node *header;
+};
+
+struct h_bin {
+ struct h_node *head;
+};
+
+struct heap {
+ u32 start;
+ u32 end;
+ struct h_bin bins[BIN_COUNT];
+};
+
+void node_add(struct h_bin *bin, struct h_node *node)
+{
+ node->magic = HEAP_MAGIC;
+ node->next = NULL;
+ node->prev = NULL;
+ if (!bin->head) {
+ bin->head = node;
+ return;
+ }
+ struct h_node *curr = bin->head;
+ struct h_node *prev = NULL;
+ while (curr && curr->size <= node->size) {
+ prev = curr;
+ curr = curr->next;
}
+ if (!curr) {
+ prev->next = node;
+ node->prev = prev;
+ } else if (prev) {
+ node->next = curr;
+ prev->next = node;
+ node->prev = prev;
+ curr->prev = node;
+ } else {
+ node->next = bin->head;
+ bin->head->prev = node;
+ bin->head = node;
+ }
+}
-#ifdef kernel
+void node_remove(struct h_bin *bin, struct h_node *node)
+{
+ if (!bin->head)
+ return;
+ if (bin->head == node) {
+ bin->head = bin->head->next;
+ return;
+ }
-static u32 *heap;
-static u32 index;
+ struct h_node *temp = bin->head->next;
+ while (temp) {
+ if (temp == node) {
+ if (!temp->next) {
+ temp->prev->next = NULL;
+ } else {
+ temp->prev->next = temp->next;
+ temp->next->prev = temp->prev;
+ }
+ return;
+ }
+ temp = temp->next;
+ }
+}
-void heap_init(u32 start)
+struct h_node *node_best_fit(struct h_bin *bin, u32 size)
{
- heap = (u32 *)start;
- for (int i = 0; i < HEAP_SIZE; i++)
- heap[i] = 0;
- heap[0] = HEAP_MAGIC;
- index = 1;
+ if (!bin->head)
+ return NULL;
+
+ struct h_node *temp = bin->head;
+ while (temp) {
+ if (temp->size >= size)
+ return temp;
+ temp = temp->next;
+ }
+ return NULL;
}
-int count()
+struct h_node *node_last(struct h_bin *bin)
{
- int i = 0;
- u32 *iterator = heap + 1;
- do {
- iterator += iterator[0] + 1;
- i++;
- } while (iterator[0] != 0);
- return i;
+ struct h_node *temp = bin->head;
+ while (temp->next)
+ temp = temp->next;
+ return temp;
}
-// TODO: Identify by pid (for freeing)
-void *malloc(u32 size)
+struct h_footer *node_foot(struct h_node *node)
{
- if (size < 1)
- return NULL;
+ return (struct h_footer *)((char *)node + sizeof(*node) + node->size);
+}
- size = size + ALIGNMENT + ALIGN_INFO;
+void node_create_foot(struct h_node *head)
+{
+ struct h_footer *foot = node_foot(head);
+ foot->header = head;
+}
- heap[index] = size;
- index += size + 1;
+u32 bin_index(u32 sz)
+{
+ u32 index = 0;
+ sz = sz < 4 ? 4 : sz;
+ while (sz >>= 1)
+ index++;
+ index -= 2;
+ if (index > BIN_MAX_IDX)
+ index = BIN_MAX_IDX;
+ return index;
+}
- void *p = (void *)(heap + index - size);
- ALIGN(p);
+/* struct h_node *wilderness_get(struct heap *heap) */
+/* { */
+/* struct h_footer *wild_foot = (struct h_footer *)((char *)heap->end - sizeof(*wild_foot)); */
+/* return wild_foot->header; */
+/* } */
- return p;
+u32 expand(struct heap *heap, u32 sz)
+{
+ (void)heap;
+ (void)sz;
+ return 0;
}
-// TODO: Implement free, realloc and find_smallest_hole
-void free(void *ptr)
+u32 contract(struct heap *heap, u32 sz)
{
- (void)ptr;
- /* UNALIGN(ptr); */
+ (void)heap;
+ (void)sz;
+ return 0;
}
-void *realloc(void *ptr, u32 size)
+static struct heap heap = { 0 };
+void heap_init(u32 start)
{
- (void)size;
- return ptr;
+ struct h_node *init_region = (struct h_node *)start;
+ init_region->hole = 1;
+ init_region->size = HEAP_INIT_SIZE - OVERHEAD;
+ node_create_foot(init_region);
+ node_add(&heap.bins[bin_index(init_region->size)], init_region);
+ heap.start = start;
+ heap.end = start + HEAP_INIT_SIZE;
}
-#elif defined(userspace)
+void *_malloc(u32 size)
+{
+ malloc_allocated += size;
+ u32 index = bin_index(size);
+ struct h_bin *temp = (struct h_bin *)&heap.bins[index];
+ struct h_node *found = node_best_fit(temp, size);
-#define HEAP_SIZE 100000
+ while (!found) {
+ assert(index + 1 < BIN_COUNT);
-#define kmalloc(n) (void *)sys1(SYS_MALLOC, n)
-#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr))
+ temp = &heap.bins[++index];
+ found = node_best_fit(temp, size);
+ }
-/* static u32 *heap = NULL; */
-/* static u32 index = 0; */
-/* static u32 malloced = 0; */
+ assert(found->magic == HEAP_MAGIC);
-// TODO: Fix userspace malloc (for size > HEAP_SIZE)!
-void *malloc(u32 size)
-{
- return kmalloc(size);
+ if ((found->size - size) > (OVERHEAD + MIN_ALLOC_SZ)) {
+ struct h_node *split = (struct h_node *)(((char *)found + OVERHEAD) + size);
+ split->magic = HEAP_MAGIC;
+ split->size = found->size - size - OVERHEAD;
+ split->hole = 1;
- /* if (size < 1) */
- /* return NULL; */
+ node_create_foot(split);
- /* size = size + ALIGNMENT + ALIGN_INFO; */
+ u32 new_idx = bin_index(split->size);
- /* if (!malloced || size > malloced) { */
- /* heap = kmalloc(HEAP_SIZE); */
- /* malloced = HEAP_SIZE; */
+ node_add(&heap.bins[new_idx], split);
+
+ found->size = size;
+ node_create_foot(found);
+ }
+
+ found->hole = 0;
+ node_remove(&heap.bins[index], found);
+
+ // TODO: Implement expand/contract
+ /* struct h_node *wild = wilderness_get(&heap); */
+ /* if (wild->size < MIN_WILDERNESS) { */
+ /* assert(expand(&heap, 0x1000)); */
+ /* } else if (wild->size > MAX_WILDERNESS) { */
+ /* assert(contract(&heap, 0x1000)); */
/* } */
- /* malloced -= size; */
- /* heap[index] = size; */
- /* index += size + 1; */
+ found->prev = NULL;
+ found->next = NULL;
+ return &found->next;
+}
+
+void _free(void *p)
+{
+ if (!p)
+ return;
+
+ struct h_bin *list;
+ struct h_footer *new_foot, *old_foot;
+
+ struct h_node *head = (struct h_node *)((char *)p - 12);
+ assert(head->magic == HEAP_MAGIC && head->hole == 0);
+ malloc_allocated -= head->size;
+ if (head == (struct h_node *)(u32 *)heap.start) {
+ head->hole = 1;
+ node_add(&heap.bins[bin_index(head->size)], head);
+ return;
+ }
+
+ struct h_node *next = (struct h_node *)((char *)node_foot(head) + sizeof(struct h_footer));
+ struct h_footer *f = (struct h_footer *)((char *)head - sizeof(struct h_footer));
+ struct h_node *prev = f->header;
+
+ if (prev->hole) {
+ list = &heap.bins[bin_index(prev->size)];
+ node_remove(list, prev);
+
+ prev->size += OVERHEAD + head->size;
+ new_foot = node_foot(head);
+ new_foot->header = prev;
+
+ head = prev;
+ }
+
+ if (next->hole) {
+ list = &heap.bins[bin_index(next->size)];
+ node_remove(list, next);
+
+ head->size += OVERHEAD + next->size;
+
+ old_foot = node_foot(next);
+ old_foot->header = 0;
+ next->size = 0;
+ next->hole = 0;
+
+ new_foot = node_foot(head);
+ new_foot->header = head;
+ }
+
+ head->hole = 1;
+ node_add(&heap.bins[bin_index(head->size)], head);
+}
- /* void *p = (void *)(heap + index - size); */
- /* ALIGN(p); */
+#elif defined(userspace)
+
+#define kmalloc(n) (void *)sys1(SYS_MALLOC, n)
+#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr))
+
+void *_malloc(u32 size)
+{
+ return kmalloc(size);
+}
- /* return p; */
+void _free(void *ptr)
+{
+ kfree(ptr);
}
-// TODO: Implement free, realloc and find_smallest_hole
-void free(void *ptr)
+#endif
+
+void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp)
{
- (void)ptr;
- /* UNALIGN(ptr); */
+ void *ret = _malloc(size);
+#ifdef kernel
+ printf("K");
+#else
+ printf("U");
+#endif
+ printf("MALLOC\t%s:%d: %s: 0x%x %dB (%s)\n", file, line, func, ret, size, inp);
+ return ret;
}
+void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp)
+{
+#ifdef kernel
+ printf("K");
+#else
+ printf("U");
#endif
+ printf("FREE\t%s:%d: %s: 0x%x (%s)\n", file, line, func, ptr, inp);
+ if (ptr)
+ _free(ptr);
+}
diff --git a/libc/stack.c b/libc/stack.c
new file mode 100644
index 0000000..c47dd59
--- /dev/null
+++ b/libc/stack.c
@@ -0,0 +1,125 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <def.h>
+#include <mem.h>
+#include <stack.h>
+
+static int nonce = 0;
+
+struct stack *stack_new()
+{
+ struct stack *stack = malloc(sizeof(*stack));
+ stack->tail = NULL;
+ return stack;
+}
+
+void stack_destroy(struct stack *stack)
+{
+ struct stack_node *iterator = stack->tail;
+ while (iterator) {
+ if (!iterator->prev) {
+ free(iterator);
+ break;
+ }
+ iterator = iterator->prev;
+ free(iterator->next);
+ }
+ stack->tail = NULL;
+ free(stack);
+ stack = NULL;
+}
+
+struct stack_node *stack_new_node()
+{
+ struct stack_node *node = malloc(sizeof(*node));
+ node->data = NULL;
+ node->prev = NULL;
+ node->next = NULL;
+ node->nonce = nonce++;
+ return node;
+}
+
+u32 stack_push_bot_node(struct stack *stack, struct stack_node *node)
+{
+ if (!stack || !node)
+ return 0;
+
+ if (stack->tail) {
+ struct stack_node *iterator = stack->tail;
+ while (iterator) {
+ if (!iterator->prev)
+ break;
+ iterator = iterator->prev;
+ }
+ iterator->prev = node;
+ node->next = iterator;
+ } else {
+ stack->tail = node;
+ }
+
+ return 1;
+}
+
+u32 stack_push_node(struct stack *stack, struct stack_node *node)
+{
+ if (!stack || !node)
+ return 0;
+
+ if (stack->tail) {
+ stack->tail->next = node;
+ node->prev = stack->tail;
+ stack->tail = node;
+ } else {
+ stack->tail = node;
+ }
+
+ return 1;
+}
+
+u32 stack_empty(struct stack *stack)
+{
+ return !stack->tail;
+}
+
+u32 stack_push_bot(struct stack *stack, void *data)
+{
+ struct stack_node *node = stack_new_node();
+ node->data = data;
+ return stack_push_bot_node(stack, node);
+}
+
+u32 stack_push(struct stack *stack, void *data)
+{
+ struct stack_node *node = stack_new_node();
+ node->data = data;
+ return stack_push_node(stack, node);
+}
+
+void *stack_pop(struct stack *stack)
+{
+ if (!stack || !stack->tail)
+ return NULL;
+
+ struct stack_node *prev = stack->tail;
+
+ stack->tail->prev->next = NULL;
+ stack->tail = stack->tail->prev;
+
+ void *data = prev->data;
+ free(prev);
+ return data;
+}
+
+void *stack_peek(struct stack *stack)
+{
+ if (!stack || !stack->tail)
+ return NULL;
+
+ return stack->tail;
+}
+
+void stack_clear(struct stack *stack)
+{
+ while (stack_pop(stack))
+ ;
+}
diff --git a/libgui/gfx.c b/libgui/gfx.c
index 3eb388a..986ecda 100644
--- a/libgui/gfx.c
+++ b/libgui/gfx.c
@@ -96,6 +96,14 @@ static void draw_rectangle(struct context *ctx, int x1, int y1, int x2, int y2,
}
}
+struct context *gfx_new_ctx(struct context *ctx)
+{
+ //struct message msg = { 0 };
+ //msg_send(2, GFX_NEW_CONTEXT, ctx);
+ //memcpy(ctx, msg_receive_loop(&msg)->data, sizeof(*ctx));
+ return ctx;
+}
+
// On-demand font loading
struct font *gfx_resolve_font(enum font_type font_type)
{
diff --git a/libgui/gui.c b/libgui/gui.c
index afbc3ba..9b49c2e 100644
--- a/libgui/gui.c
+++ b/libgui/gui.c
@@ -465,6 +465,7 @@ struct element *gui_add_text_input(struct element *container, int x, int y, u32
((struct element_text_input *)text_input->data)->x = x;
((struct element_text_input *)text_input->data)->y = y;
((struct element_text_input *)text_input->data)->width = width;
+ ((struct element_text_input *)text_input->data)->text[0] = '\0';
((struct element_text_input *)text_input->data)->color_fg = color_fg;
((struct element_text_input *)text_input->data)->color_bg = color_bg;
((struct element_text_input *)text_input->data)->font_type = font_type;
@@ -530,28 +531,28 @@ void gui_event_loop(struct element *container)
if (!container)
return;
- struct message *msg;
+ struct message msg = { 0 };
struct element *focused = NULL;
while (1) {
- if (!(msg = msg_receive())) {
- yield();
- continue;
- }
+ /* if (!msg_receive(&msg)) { */
+ yield();
+ continue;
+ /* } */
- switch (msg->type) {
+ switch (msg.type) {
case GUI_KILL: {
remove_all();
exit(0);
}
case GUI_MOUSE: {
- struct gui_event_mouse *event = msg->data;
+ struct gui_event_mouse *event = msg.data;
focused = element_at(container, event->x, event->y);
if (focused && focused->event.on_click && event->but1)
focused->event.on_click(event, focused);
break;
}
case GUI_KEYBOARD: {
- struct gui_event_keyboard *event = msg->data;
+ struct gui_event_keyboard *event = msg.data;
if (focused && focused->type == GUI_TYPE_TEXT_INPUT && event->press) {
char *s = ((struct element_text_input *)focused->data)->text;
@@ -583,14 +584,13 @@ void gui_event_loop(struct element *container)
break;
}
case GUI_RESIZE: {
- struct gui_event_resize *event = msg->data;
+ struct gui_event_resize *event = msg.data;
struct element *root = get_root(container->window_id);
root->ctx = event->new_ctx;
gui_sync_window(container->window_id);
break;
}
}
- free(msg);
}
exit(1);
diff --git a/libgui/inc/gfx.h b/libgui/inc/gfx.h
index 0f4c631..718fd28 100644
--- a/libgui/inc/gfx.h
+++ b/libgui/inc/gfx.h
@@ -64,6 +64,7 @@ struct context {
int flags;
};
+struct context *gfx_new_ctx(struct context *ctx);
struct font *gfx_resolve_font(enum font_type font_type);
void gfx_write_char(struct context *ctx, int x, int y, enum font_type font_type, u32 c, char ch);
void gfx_write(struct context *ctx, int x, int y, enum font_type font_type, u32 c,
@@ -83,9 +84,8 @@ int gfx_font_width(enum font_type);
* Wrappers
*/
-#define gfx_new_ctx(ctx) \
- (msg_send(2, GFX_NEW_CONTEXT, (ctx)), (struct context *)msg_receive_loop()->data)
-#define gfx_redraw() (msg_send(2, GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization)
-#define gfx_redraw_focused() (msg_send(2, GFX_REDRAW_FOCUSED, NULL))
+#define gfx_redraw() \
+ (void)42 //(msg_send(2, GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization)
+#define gfx_redraw_focused() (void)42 //(msg_send(2, GFX_REDRAW_FOCUSED, NULL))
#endif
diff --git a/libgui/png.c b/libgui/png.c
index 2db6e4d..ad65eba 100644
--- a/libgui/png.c
+++ b/libgui/png.c
@@ -1125,9 +1125,8 @@ static struct png *png_new(void)
void png_free(struct png *png)
{
// Deallocate image buffer
- /* if (png->buffer != NULL) { */
- /* free(png->buffer); */
- /* } */
+ if (png->buffer)
+ free(png->buffer);
// Deallocate source buffer, if necessary
png_free_source(png);
@@ -1167,7 +1166,7 @@ struct bmp *png_load(const char *path)
return NULL;
void *buf = sread(path);
- if (!png) {
+ if (!buf) {
SET_ERROR(png, PNG_ENOTFOUND);
png_free(png);
return NULL;
@@ -1190,7 +1189,6 @@ struct bmp *png_load(const char *path)
bmp->pitch = png->width * (bmp->bpp >> 3);
png_free(png);
- free(buf);
return bmp;
}