summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/video/fbdev.c49
-rw-r--r--sys/include/sys/device.h2
-rw-r--r--sys/include/sys/fbdev.h40
-rw-r--r--sys/include/sys/mman.h22
-rw-r--r--sys/include/sys/syscall.h2
-rw-r--r--sys/kern/kern_syscall.c3
-rw-r--r--sys/vm/vm_map.c44
7 files changed, 135 insertions, 27 deletions
diff --git a/sys/dev/video/fbdev.c b/sys/dev/video/fbdev.c
index 391400c..8a2499d 100644
--- a/sys/dev/video/fbdev.c
+++ b/sys/dev/video/fbdev.c
@@ -28,36 +28,65 @@
*/
#include <sys/types.h>
+#include <sys/errno.h>
#include <sys/limine.h>
#include <sys/device.h>
#include <sys/driver.h>
+#include <sys/fbdev.h>
#include <dev/video/fbdev.h>
#include <fs/devfs.h>
+#include <fs/ctlfs.h>
#include <vm/vm.h>
+#include <string.h>
#define FRAMEBUFFER \
framebuffer_req.response->framebuffers[0]
static struct cdevsw fb_cdevsw;
+static const struct ctlops fb_size_ctl;
static volatile struct limine_framebuffer_request framebuffer_req = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0
};
static paddr_t
-fbdev_mmap(dev_t dev, off_t off, int flags)
+fbdev_mmap(dev_t dev, size_t size, off_t off, int flags)
{
size_t max_bounds;
max_bounds = FRAMEBUFFER->pitch * FRAMEBUFFER->height;
- max_bounds /= 4;
- if (off > max_bounds) {
+ if ((off + size) > max_bounds) {
return 0;
}
return VIRT_TO_PHYS(FRAMEBUFFER->address);
}
+static int
+ctl_attr_read(struct ctlfs_dev *cdp, struct sio_txn *sio)
+{
+ struct fbattr attr;
+ size_t len = sizeof(attr);
+
+ if (sio == NULL) {
+ return -EINVAL;
+ }
+ if (sio->buf == NULL) {
+ return -EINVAL;
+ }
+
+ if (len > sio->len) {
+ len = sio->len;
+ }
+
+ attr.width = FRAMEBUFFER->width;
+ attr.height = FRAMEBUFFER->height;
+ attr.pitch = FRAMEBUFFER->pitch;
+ attr.bpp = FRAMEBUFFER->bpp;
+ memcpy(sio->buf, &attr, len);
+ return len;
+}
+
struct fbdev
fbdev_get(void)
{
@@ -74,6 +103,7 @@ fbdev_get(void)
static int
fbdev_init(void)
{
+ struct ctlfs_dev ctl;
char devname[] = "fb0";
devmajor_t major;
dev_t dev;
@@ -83,6 +113,14 @@ fbdev_init(void)
dev = dev_alloc(major);
dev_register(major, dev, &fb_cdevsw);
devfs_create_entry(devname, major, dev, 0444);
+
+
+ /* Register control files */
+ ctl.mode = 0444;
+ ctlfs_create_node(devname, &ctl);
+ ctl.devname = devname;
+ ctl.ops = &fb_size_ctl;
+ ctlfs_create_entry("attr", &ctl);
return 0;
}
@@ -92,4 +130,9 @@ static struct cdevsw fb_cdevsw = {
.mmap = fbdev_mmap
};
+static const struct ctlops fb_size_ctl = {
+ .read = ctl_attr_read,
+ .write = NULL,
+};
+
DRIVER_EXPORT(fbdev_init);
diff --git a/sys/include/sys/device.h b/sys/include/sys/device.h
index cb2a702..04b66fc 100644
--- a/sys/include/sys/device.h
+++ b/sys/include/sys/device.h
@@ -48,7 +48,7 @@ typedef int(*dev_bsize_t)(dev_t);
struct cdevsw {
int(*read)(dev_t dev, struct sio_txn *sio, int flags);
int(*write)(dev_t dev, struct sio_txn *sio, int flags);
- paddr_t(*mmap)(dev_t dev, off_t off, int flags);
+ paddr_t(*mmap)(dev_t dev, size_t size, off_t off, int flags);
/* Private */
struct vm_object vmobj;
diff --git a/sys/include/sys/fbdev.h b/sys/include/sys/fbdev.h
new file mode 100644
index 0000000..e206889
--- /dev/null
+++ b/sys/include/sys/fbdev.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_FBDEV_H_
+#define _SYS_FBDEV_H_
+
+struct fbattr {
+ uint32_t width;
+ uint32_t height;
+ uint32_t pitch;
+ uint32_t bpp;
+};
+
+#endif /* !_SYS_FBDEV_H_ */
diff --git a/sys/include/sys/mman.h b/sys/include/sys/mman.h
index 4ead9ba..08f506d 100644
--- a/sys/include/sys/mman.h
+++ b/sys/include/sys/mman.h
@@ -35,6 +35,8 @@
#if defined(_KERNEL)
#include <sys/tree.h>
#include <vm/vm_obj.h>
+#else
+#include <stddef.h>
#endif /* _KERNEL */
/*
@@ -80,19 +82,19 @@ struct mmap_lgdr {
size_t nbytes;
};
-/* Kernel munmap() routine */
-int munmap_at(void *addr, size_t len);
-
-/* Kernel mmap() routine */
-void *mmap_at(void *addr, size_t len, int prot, int flags,
- int fildes, off_t off);
-
int mmap_entrycmp(const struct mmap_entry *a, const struct mmap_entry *b);
RBT_PROTOTYPE(lgdr_entries, mmap_entry, hd, mmap_entrycmp)
-#endif /* _KERNEL */
/* Syscall layer */
-scret_t mmap(struct syscall_args *scargs);
-scret_t munmap(struct syscall_args *scargs);
+scret_t sys_mmap(struct syscall_args *scargs);
+scret_t sys_munmap(struct syscall_args *scargs);
+#endif /* _KERNEL */
+
+/* Kernel munmap() routine */
+int munmap(void *addr, size_t len);
+
+/* Kernel mmap() routine */
+void *mmap(void *addr, size_t len, int prot, int flags,
+ int fildes, off_t off);
#endif /* !_SYS_MMAN_H_ */
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h
index 2223a96..dad2e00 100644
--- a/sys/include/sys/syscall.h
+++ b/sys/include/sys/syscall.h
@@ -48,6 +48,8 @@
#define SYS_write 7
#define SYS_spawn 8
#define SYS_reboot 9
+#define SYS_mmap 10
+#define SYS_munmap 11
#if defined(_KERNEL)
/* Syscall return value and arg type */
diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c
index 249a04a..8a66f0e 100644
--- a/sys/kern/kern_syscall.c
+++ b/sys/kern/kern_syscall.c
@@ -31,6 +31,7 @@
#include <sys/sysctl.h>
#include <sys/reboot.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include <sys/proc.h>
#include <sys/vfs.h>
@@ -45,6 +46,8 @@ scret_t(*g_sctab[])(struct syscall_args *) = {
sys_write, /* SYS_write */
sys_spawn, /* SYS_spawn */
sys_reboot, /* SYS_reboot */
+ sys_mmap, /* SYS_mmap */
+ sys_munmap, /* SYS_munap */
};
const size_t MAX_SYSCALLS = NELEM(g_sctab);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index b8f4aee..0ff3763 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -159,7 +159,7 @@ vm_map_modify(struct vas vas, vaddr_t va, paddr_t pa, vm_prot_t prot, bool unmap
* crashes.
*/
void *
-mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
+mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
struct vm_object *map_obj = NULL;
struct cdevsw *cdevp;
@@ -179,11 +179,6 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
npgs = len / DEFAULT_PAGESIZE;
vas = pmap_read_vas();
- if (addr == NULL) {
- pr_error("mmap: NULL addr not supported\n");
- return NULL;
- }
-
/* Validate flags */
if (ISSET(flags, MAP_FIXED)) {
pr_error("mmap: fixed mappings not yet supported\n");
@@ -216,11 +211,29 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
}
cdevp = map_obj->data;
- if ((pa = cdevp->mmap(vp->dev, off, 0)) == 0) {
+ if ((pa = cdevp->mmap(vp->dev, len, off, 0)) == 0) {
kprintf("mmap: dev mmap() gave 0\n");
return NULL;
}
+ /*
+ * If the address passed is NULL, just identity
+ * map everything.
+ *
+ * XXX: This is why the bounds check done in the
+ * cdev mmap() *must* be correct.
+ *
+ * TODO: Use copy-on-write for this instead. Since mapping
+ * certain devices may required a lot of memory to
+ * be referenced anyways, we could use a buffered
+ * copy-on-write technique where only a window of
+ * pages can be mapped on-demand and other pages
+ * freed when that window is exceeded.
+ */
+ if (addr == NULL) {
+ addr = (void *)pa;
+ }
+
va = ALIGN_DOWN((vaddr_t)addr, DEFAULT_PAGESIZE);
error = vm_map(vas, va, pa, prot, len);
if (error != 0) {
@@ -231,6 +244,11 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
goto done;
}
+ if (addr == NULL) {
+ pr_error("mmap: NULL addr not supported\n");
+ return NULL;
+ }
+
/* Only allocate new obj if needed */
if (map_obj == NULL) {
map_obj = dynalloc(sizeof(*map_obj));
@@ -292,7 +310,7 @@ done:
* multiple of the machine page size.
*/
int
-munmap_at(void *addr, size_t len)
+munmap(void *addr, size_t len)
{
int pgno;
vaddr_t va;
@@ -348,7 +366,7 @@ munmap_at(void *addr, size_t len)
* arg5 -> off
*/
scret_t
-mmap(struct syscall_args *scargs)
+sys_mmap(struct syscall_args *scargs)
{
void *addr;
size_t len;
@@ -357,11 +375,11 @@ mmap(struct syscall_args *scargs)
addr = (void *)scargs->arg0;
len = scargs->arg1;
- prot = scargs->arg2;
+ prot = scargs->arg2 | PROT_USER;
flags = scargs->arg3;
fildes = scargs->arg4;
off = scargs->arg5;
- return (scret_t)mmap_at(addr, len, prot, flags, fildes, off);
+ return (scret_t)mmap(addr, len, prot, flags, fildes, off);
}
/*
@@ -371,14 +389,14 @@ mmap(struct syscall_args *scargs)
* arg1 -> len
*/
scret_t
-munmap(struct syscall_args *scargs)
+sys_munmap(struct syscall_args *scargs)
{
void *addr;
size_t len;
addr = (void *)scargs->arg0;
len = scargs->arg1;
- return (scret_t)munmap_at(addr, len);
+ return (scret_t)munmap(addr, len);
}
/*