#include "fs/devices/Framebuffer.h" #include "std/stdio.h" #include "std/stdlib.h" #include "std/string.h" #include "memory/MemoryManager.h" #include "utils/Addresses.h" #include "misc/utils.h" #include "std/errno.h" #include "bootboot.h" extern BOOTBOOT bootboot; extern char fb[1]; #define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno) extern uint64_t clock_now(); VFS::Node* FramebufferDevice::create_new(const char* devname) { VFS::Node* dev = new VFS::Node; dev->write_func = FramebufferDevice::write; dev->mmap_func = FramebufferDevice::mmap; dev->ioctl_func = FramebufferDevice::ioctl; dev->inode = 0; dev->length = 0; dev->type = VFS_DEVICE; dev->flags = 0; dev->uid = dev->gid = 0; dev->mode = 0222; dev->atime = dev->ctime = dev->mtime = clock_now(); strncpy(dev->name, devname, sizeof(dev->name)); return dev; } uintptr_t FramebufferDevice::mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset) { if (!node) return -1; int real_prot = prot & ~(MAP_AS_OWNED_BY_TASK); if(round_down_to_nearest_page(offset) != (uintptr_t)offset) { return MAP_FAIL(EINVAL); } if((size + offset) > bootboot.fb_size) { return MAP_FAIL(ERANGE); // FIXME: Should probably be EOVERFLOW. } MemoryManager::map_several_pages(bootboot.fb_ptr + offset, addr, Utilities::get_blocks_from_size(PAGE_SIZE, size), real_prot); return addr; } ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, const char* buffer) { if (!node) return -1; if((size + offset) > (uint64_t)bootboot.fb_size) { size = (uint64_t)bootboot.fb_size - offset; } memcpy(fb + offset, buffer, size); return (ssize_t)size; } #define FB_GET_WIDTH 0 #define FB_GET_HEIGHT 1 long FramebufferDevice::ioctl(VFS::Node* node, int cmd, uintptr_t) { if (!node) return -1; switch(cmd) { case FB_GET_WIDTH: return (long)bootboot.fb_width; case FB_GET_HEIGHT: return (long)bootboot.fb_height; default: return -EINVAL; } }