diff options
-rw-r--r-- | Makefile.in | 8 | ||||
-rw-r--r-- | README.md | 34 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/Makefile | 9 | ||||
-rw-r--r-- | lib/libc/src/hyra/socket.c | 18 | ||||
-rw-r--r-- | lib/libgfx/Makefile | 30 | ||||
-rw-r--r-- | lib/libgfx/include/libgfx/draw.h | 91 | ||||
-rw-r--r-- | lib/libgfx/include/libgfx/gfx.h | 85 | ||||
-rw-r--r-- | lib/libgfx/src/draw.c | 96 | ||||
-rw-r--r-- | lib/libgfx/src/gfx.c | 97 | ||||
-rw-r--r-- | share/docs/kernel/ctlfs.md | 125 | ||||
-rw-r--r-- | share/man/man1/osh.1 | 83 | ||||
-rw-r--r-- | sys/dev/dmi/dmi.c | 57 | ||||
-rw-r--r-- | sys/dev/dmi/dmi_board.c | 104 | ||||
-rw-r--r-- | sys/include/dev/dmi/dmi.h | 2 | ||||
-rw-r--r-- | sys/include/dev/dmi/dmivar.h | 41 | ||||
-rw-r--r-- | sys/include/fs/ctlfs.h | 6 | ||||
-rw-r--r-- | sys/include/sys/dmi.h | 63 | ||||
-rw-r--r-- | usr.bin/Makefile | 1 | ||||
-rw-r--r-- | usr.bin/dmidump/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/dmidump/dmidump.c | 78 | ||||
-rw-r--r-- | usr.bin/mrow/Makefile | 2 | ||||
-rw-r--r-- | usr.bin/mrow/mrow.c | 73 |
23 files changed, 1050 insertions, 61 deletions
diff --git a/Makefile.in b/Makefile.in index 42a0f94..a7d84c4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,7 +67,7 @@ override USRDIR = $(shell pwd)/base/usr .PHONY: all -all: stand/boot/ libc sbin bin base/boot/hyra.krq +all: stand/boot/ libs sbin bin base/boot/hyra.krq rm -f sys/include/machine .PHONY: sbin @@ -82,9 +82,9 @@ bin: $(BIN_MAKEDIRS) ROOT=$(PROJECT_ROOT) OSVER=$(HYRA_VERSION) OSARCH=$(ARCH)\ CC="$(CC)" -.PHONY: libc -libc: - $(MAKE) -C lib/libc/ -I$(shell pwd)/builddeps \ +.PHONY: libs +libs: + $(MAKE) -C lib/ -I$(shell pwd)/builddeps \ USRDIR=$(USRDIR) ARCH=$(ARCH) ROOT=$(PROJECT_ROOT) \ CC="$(CC)" @@ -1,14 +1,22 @@ The Hyra Operating System ========================= -Welcome to the Hyra Operating System project! +Welcome to the Hyra Operating System project! Hyra is an experimental +operating system inspired by BSD and Plan 9 while being entirely written from scratch. +Hyra aims to rethink core fundamentals in modern operating system design in order to +create new and improved architectural ideas. + Project Goal: -------------- -The goal of this project is to redefine what modern operating systems are while taking inspiration from BSD. Hyra does not use -POSIX by default and instead uses the [OSMORA Uniform System Interface (OUSI)](https://osmora.org/oap/oap-0002). Hyra also does +The goal of this project is to redefine what modern operating systems are while taking inspiration from BSD. Hyra does not use CPIO for its initramfs like other operating systems typically would and instead uses the [OSMORA Archive Format (OMAR)](https://osmora.org/oap/oap-0005). +What Hyra is NOT: +-------------- +Hyra is *NOT* Linux, nor does extend or share any sources with any existing +operating systems as it is written entirely from scratch. Hyra is *NOT* intended as a "toy" project as it is aimed to be the used as the main operating system for internal OSMORA operations and infrastructure. + Getting Started: ---------------- To build Hyra you'll need to bootstrap the project which is essentially just fetching dependencies for the project. This can be done by running the bootstrap script within the project root: `./bootstrap`. @@ -31,7 +39,7 @@ password is also `root`. Programs: ---------------- -The Hyra userspace provides the user various programs that they can run, examples of +The Hyra userspace provides the user various programs that they can run. Examples of such programs include: - ``beep`` - Play a tone @@ -47,12 +55,28 @@ such programs include: - ``readcore`` - Read coredump files - ``oasm`` - OSMORA [OSMX64](https://github.com/sigsegv7/OSMX64) Assembler - ``oemu`` - OSMORA [OSMX64](https://github.com/sigsegv7/OSMX64) Emulator +- ``kstat`` - Read kernel statistics +- ``dmidump`` - Dump DMI/SMBios information And more! See ``usr.bin/*`` +Libraries: +---------------- +The Hyra userspace additionally provides the user various libraries that they can +link with. Examples of such libraries include: + +- ``libc`` - C library (link flag: ``-lc``) +- ``libgfx`` - Low-level graphics (link flag: ``-lgfx``) + +And more! See ``lib/*`` + Documentation: -------------- -Documentation will be in the form of comments throughout the codebase and can also be found in the share/ directory within the project root. +Documentation will be in the form of comments throughout the codebase and can also be found in: + +- ``share/man/*``: Man pages +- ``share/contrib``: Information on contributing +- ``share/docs/kernel``: Kernel documentation Hyra running on bare metal: -------------- diff --git a/configure.ac b/configure.ac index ecbeafe..6db3a09 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([Hyra], [2.4], [ian@osmora.org]) +AC_INIT([Hyra], [2.5], [ian@osmora.org]) TARGET="amd64" QEMU="qemu-system-x86_64" diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..4ad104b --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,9 @@ +LDSCRIPT = +USRDIR = +ROOT = +ARGS = -I$(ROOT)/builddeps LDSCRIPT=$(LDSCRIPT) USRDIR=$(USRDIR) ROOT=$(ROOT) + +.PHONY: all +all: + make -C libc/ $(ARGS) + make -C libgfx/ $(ARGS) diff --git a/lib/libc/src/hyra/socket.c b/lib/libc/src/hyra/socket.c index 99e0200..b3039f6 100644 --- a/lib/libc/src/hyra/socket.c +++ b/lib/libc/src/hyra/socket.c @@ -53,3 +53,21 @@ recv(int sockfd, void *buf, size_t len, int flags) { return syscall(SYS_recv, sockfd, (uintptr_t)buf, len, flags); } + +ssize_t +sendmsg(int socket, const struct msghdr *msg, int flags) +{ + return syscall(SYS_sendmsg, socket, (uintptr_t)msg, flags); +} + +ssize_t +recvmsg(int socket, struct msghdr *msg, int flags) +{ + return syscall(SYS_recvmsg, socket, (uintptr_t)msg, flags); +} + +int +connect(int socket, const struct sockaddr *address, socklen_t len) +{ + return syscall(SYS_connect, socket, (uintptr_t)address, len); +} diff --git a/lib/libgfx/Makefile b/lib/libgfx/Makefile new file mode 100644 index 0000000..1f866ac --- /dev/null +++ b/lib/libgfx/Makefile @@ -0,0 +1,30 @@ +CFLAGS = -c -fno-stack-protector -nostdlib -static \ + -Iinclude/ -I$(USRDIR)/include/ +CFILES = $(shell find src/ -name "*.c") +OBJ = $(CFILES:.c=.o) + +all: headers $(OBJ) build/libgfx.a + echo "----------------------------------------" + echo $(USRDIR) + mv build/libgfx.a $(USRDIR)/lib/ + cp -r include/ $(USRDIR)/include/ + +build/libgfx.a: + mkdir -p build/ + ar rcs build/libgfx.a $(OBJ) + +%.o: %.c + $(CC) $(CFLAGS) -Iinclude/ $< -o $@ + +.PHONY: headers +headers: + cp -rf include/* $(USRDIR)/include/ + +.PHONY: +build/: + mkdir -p build/ + +.PHONY: clean +clean: + rm -f $(OBJ) + rm -rf build/ diff --git a/lib/libgfx/include/libgfx/draw.h b/lib/libgfx/include/libgfx/draw.h new file mode 100644 index 0000000..60d2b24 --- /dev/null +++ b/lib/libgfx/include/libgfx/draw.h @@ -0,0 +1,91 @@ +/* + * 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 _LIBGFX_DRAW_H_ +#define _LIBGFX_DRAW_H_ + +#include <stdint.h> +#include <libgfx/gfx.h> + +/* Shape types */ +#define SHAPE_SQUARE 0x00000000 + +/* + * Default shape initializer, something that + * works and can be tweaked. The idea of this + * is so that shapes may be set up like so: + * + * -- + * struct gfx_shape blah = GFX_SHAPE_DEFAULT; + * + * blah.width = width; + * blah.heiht = height; + * ... + * -- + */ +#define GFX_SHAPE_DEFAULT \ + { \ + .type = SHAPE_SQUARE, \ + .color = 0x00FF00, \ + .x = 0, \ + .y = 0, \ + .width = 50, \ + .height = 50, \ + } + +/* + * Generic shape representation + * + * @type: Shape type (see SHAPE_*) + * @color: Color of the shape + * @x: X position of the shape + * @y: Y position of the shape + * @width: Shape width + * @height: Shape height + */ +struct gfx_shape { + uint32_t type; + color_t color; + scrpos_t x; + scrpos_t y; + dimm_t width; + dimm_t height; +}; + +int gfx_draw_shape(struct gfx_ctx *ctx, const struct gfx_shape *shape); + +__always_inline static inline size_t +gfx_io_index(struct gfx_ctx *ctx, scrpos_t x, scrpos_t y) +{ + struct fbattr fbdev = ctx->fbdev; + + return x + y * (fbdev.pitch / 4); +} + +#endif /* !_LIBGFX_DRAW_H_ */ diff --git a/lib/libgfx/include/libgfx/gfx.h b/lib/libgfx/include/libgfx/gfx.h new file mode 100644 index 0000000..3468571 --- /dev/null +++ b/lib/libgfx/include/libgfx/gfx.h @@ -0,0 +1,85 @@ +/* + * 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 _LIBGFX_H_ +#define _LIBGFX_H_ + +#include <sys/fbdev.h> +#include <stdint.h> +#include <stdio.h> + +#define gfx_log(fmt, ...) printf( "libgfx: " fmt, ##__VA_ARGS__) + +/* + * Represents a 32-bit pixel value. + * + * 24:16 15:8 7:0 + * +-----------------+ + * | R | B | B | + * +-----------------+ + */ +typedef uint32_t pixel_t; +typedef pixel_t color_t; + +/* + * Basic color defines + */ +#define GFX_BLACK 0x000000 +#define GFX_RED 0xFF0000 +#define GFX_GREEN 0x00FF00 +#define GFX_BLUE 0x0000FF +#define GFX_WHITE 0xFFFFFF +#define GFX_PURPLE 0x800080 +#define GFX_YELLOW 0xFFFF00 + +/* + * Represents cartesian x/y values + */ +typedef uint32_t cartpos_t; +typedef cartpos_t scrpos_t; +typedef cartpos_t dimm_t; /* Dimensions */ + +/* + * Graphics context for libgfx + * + * @fbdev: Framebuffer attributes + * @io: Framebuffer pointer + * @fbfd: Framebuffer file descriptor + */ +struct gfx_ctx { + struct fbattr fbdev; + size_t fb_size; + pixel_t *io; + int fbfd; +}; + +int gfx_init(struct gfx_ctx *res); +void gfx_cleanup(struct gfx_ctx *ctx); + +#endif /* !_LIBGFX_H_ */ diff --git a/lib/libgfx/src/draw.c b/lib/libgfx/src/draw.c new file mode 100644 index 0000000..49f2f53 --- /dev/null +++ b/lib/libgfx/src/draw.c @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#include <sys/errno.h> +#include <stdint.h> +#include <libgfx/gfx.h> +#include <libgfx/draw.h> + +/* + * Draw a classic square onto the screen. + * + * @ctx: Graphics context + * @shape: Square to draw + */ +static int +gfx_draw_square(struct gfx_ctx *ctx, const struct gfx_shape *shape) +{ + struct fbattr fbdev; + off_t idx; + scrpos_t scr_width, scr_height; + scrpos_t x, y; + + if (ctx == NULL || shape == NULL) { + return -EINVAL; + } + + /* Grab screen dimensions */ + fbdev = ctx->fbdev; + scr_width = fbdev.width; + scr_height = fbdev.height; + + for (x = shape->x; x < shape->x + shape->width; ++x) { + for (y = shape->y; y < shape->y + shape->height; ++y) { + if (x >= scr_width || y >= scr_height) { + break; + } + + idx = gfx_io_index(ctx, x, y); + ctx->io[idx] = shape->color; + } + } + return 0; +} + +/* + * Draw a shape onto the screen + * + * @ctx: libgfx graphics context + * @shape: Shape to draw + * + * Returns 0 on success, otherwise a less than zero + * value on failure. + * + * All error codes follow POSIX errno. However if the value + * is -1, the requested shape to be drawn is not valid. + */ +int +gfx_draw_shape(struct gfx_ctx *ctx, const struct gfx_shape *shape) +{ + if (ctx == NULL || shape == NULL) { + return -EINVAL; + } + + switch (shape->type) { + case SHAPE_SQUARE: + return gfx_draw_square(ctx, shape); + } + + return -1; +} diff --git a/lib/libgfx/src/gfx.c b/lib/libgfx/src/gfx.c new file mode 100644 index 0000000..90dcb79 --- /dev/null +++ b/lib/libgfx/src/gfx.c @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#include <sys/errno.h> +#include <sys/mman.h> +#include <sys/fbdev.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <libgfx/gfx.h> + +/* + * Initialize the libgfx context + * + * @res: Context pointer to be initialized + */ +int +gfx_init(struct gfx_ctx *res) +{ + struct fbattr attr; + int fd, prot; + + if (res == NULL) { + return -EINVAL; + } + + /* Get framebuffer attributes */ + fd = open("/ctl/fb0/attr", O_RDONLY); + if (fd < 0) { + gfx_log("could not open '/ctl/fb0/attr"); + return fd; + } + + read(fd, &attr, sizeof(attr)); + close(fd); + res->fbdev = attr; + + /* Open the framebuffer file */ + res->fbfd = open("/dev/fb0", O_RDWR); + if (res->fbfd < 0) { + gfx_log("could not open '/dev/fb0'\n"); + return res->fbfd; + } + + /* Map the framebuffer into memory */ + prot = PROT_READ | PROT_WRITE; + res->fb_size = attr.height * attr.pitch; + res->io = mmap(NULL, res->fb_size, prot, MAP_SHARED, res->fbfd, 0); + + /* Did the mmap() call work? */ + if (res->io == NULL) { + gfx_log("could not map framebuffer\n"); + close(res->fbfd); + return -1; + } + + return 0; +} + +/* + * Cleanup all state and free the gfx + * context. + */ +void +gfx_cleanup(struct gfx_ctx *ctx) +{ + if (ctx->io != NULL) + munmap(ctx->io, ctx->fb_size); + if (ctx->fbfd > 0) + close(ctx->fbfd); +} diff --git a/share/docs/kernel/ctlfs.md b/share/docs/kernel/ctlfs.md new file mode 100644 index 0000000..3087f60 --- /dev/null +++ b/share/docs/kernel/ctlfs.md @@ -0,0 +1,125 @@ +# The Hyra control filesystem (ctlfs) + +Written by Ian M. Moffett + +## Rationale + +Historically, Operating Systems of the Unix family typically relied +on syscalls like ``ioctl()`` or similar to perform operations (e.g., making calls through a driver) +via some file descriptor. Let's say for example, one wanted to acquire the framebuffer +dimensions of a given framebuffer device. To start, they'd acquire a file descriptor +by calling ``open()`` or similar on it. Then they'd make their ``ioctl()`` call. + +```c +int fd = ...; + +ioctl(fd, IOCTL_FBINFO, &fb_info); +... +``` + +While this works fine and is relatively simple to use from the user's +perspective, it is very clunky when you pop the hood and peer into the +inner-workings of it within the kernel. The number of possible requests +that can be passed through a file descriptor can grow quite rapidly which +can require really large switch statements within the drivers that implement +an ``ioctl()`` interface. + +## Replacing ``ioctl()`` + +Hyra provides ctlfs, an abstract in-memory filesystem designed for +setting/getting various kernel / driver parameters and state via +the filesystem API. The control filesystem consists of several +instances of two fundamentals: "control nodes" and "control entries". + +### Control nodes + +Control nodes are simply directories within the ``/ctl`` root. For example, +console specific control files are in the ``/ctl/console`` node. + +### Control entries + +Control entries are simply files within specific control nodes. For example +console features may be find in the ``consfeat`` entry of the ``console`` node +(i.e., ``/ctl/console/consfeat``). + +See ``sys/include/sys/console.h`` and ``sys/fs/ctlfs.h`` for more +information. + +## The ctlfs API + +The Hyra kernel provides an API for subsystems and drivers +to create their own ctlfs entries and nodes. This may be found +in sys/include/fs/ctlfs.h + +### Control operations + +Each control entry must define their own set of +"control operations" described by the ``ctlops`` structure: + +```c +struct ctlops { + int(*read)(struct ctlfs_dev *cdp, struct sio_txn *sio); + int(*write)(struct ctlfs_dev *cdp, struct sio_txn *sio); + ... +}; +``` + +NOTE: Callbacks defined as ``NULL`` will be +ignored and unused. + +## "Meow World": Creating a ctlfs entry + +```c +#include <sys/types.h> +#include <sys/sio.h> +#include <fs/ctlfs.h> + +static const struct ctlops meow_ctl; + +/* + * Ctlfs read callback - this will be called + * when "/ctl/meow/hii" is read. + */ +static int +ctl_meow_read(struct ctlfs_dev *cdp, struct sio_txn *sio) +{ + char data[] = "Meow World!"" + + /* Clamp the input length */ + if (sio->len > sizeof(data)) { + sio->len = sizeof(data) + } + + /* End of the data? */ + if ((sio->offset + sio->len) > sizeof(data)) { + return 0; + } + + /* Copy the data and return the length */ + memcpy(sio->buf, &data[sio->offset], sio->len); + return sio->len; +} + +static int +foo_init(void) +{ + char ctlname[] = "meow"; + struct ctlfs_dev ctl; + + /* + * Here we create the "/ctl/meow" node. + */ + ctl.mode = 0444; + ctl.devname = devname; + ctlfs_create_node(devname, &ctl); + + ctl.ops = &fb_size_ctl; + ctlfs_create_entry("attr", &ctl); + return 0; +} + +static const struct ctlops meow_ctl = { + .read = ctl_meow_read, + .write = NULL, +}; +``` diff --git a/share/man/man1/osh.1 b/share/man/man1/osh.1 new file mode 100644 index 0000000..1b2744c --- /dev/null +++ b/share/man/man1/osh.1 @@ -0,0 +1,83 @@ +.\" Copyright (c) 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. +.Dd Aug 2 2025 +.Dt OSH 1 +.Os HYRA +.Sh NAME +.Nm osh - OSMORA shell +.Sh SYNOPSIS +osh [optional file] + +.Sh DESCRIPTION + +OSH is a simple shell interpreter that is capable of executing commands +from the user via stdin or a shell script file passed as an argument. + +.Sh COMMENTS +OSH supports the use of comments (i.e., pieces of text ignored by the shell) +denoted by '@'. The following is an example of using comments: + +.Bd -literal +echo hello !! @ Echos the text "hello !!" +.Ed + +.Sh DEFINITIONS +OSH defines "control operators" as any character(s) reserved by OSH for +representing specific operations (e.g., background jobs, command repetition, etc): + +The +.Ft '&' +control operator is used after a command or binary path +in order to run the executable as a background job, allowing +the shell to continue immediately. Here is an example of running "sleep" in the background: +.Bd -literal +-- +@ +@ Usually this will hang the shell for 5 +@ seconds until sleep wakes up. However, +@ when we postpend '&', the shell executes +@ 'sleep' as a background job and continues +@ as usual. +@ +sleep 5 & +-- +.Ed + +The +.Ft '!!' +control operator is used to repeat the most recently used +command. This is simply written by itself like this: + +.Bd -literal +-- +echo "hewwo" @ Echo "hewwo" +!! @ Do it again... +-- +.Ed + +.Sh AUTHORS +.An Ian Moffett Aq Mt ian@osmora.org diff --git a/sys/dev/dmi/dmi.c b/sys/dev/dmi/dmi.c index 84288cf..73a9ab7 100644 --- a/sys/dev/dmi/dmi.c +++ b/sys/dev/dmi/dmi.c @@ -35,7 +35,9 @@ #include <sys/cdefs.h> #include <sys/syslog.h> #include <dev/dmi/dmi.h> +#include <dev/dmi/dmivar.h> #include <dev/acpi/tables.h> +#include <fs/ctlfs.h> #include <string.h> #define DMI_BIOS_INFO 0 @@ -46,8 +48,10 @@ /* String offsets */ #define BIOSINFO_VENDOR 0x01 #define SYSINFO_PRODUCT 0x02 -#define SYSINFO_FAMILY 0x03 +#define SYSINFO_VERSION 0x03 +#define SYSINFO_FAMILY 0x06 #define PROCINFO_MANUFACT 0x02 +#define PROCINFO_VERSION 0x03 #define PROCINFO_PARTNO 0x06 static struct limine_smbios_request smbios_req = { @@ -177,6 +181,24 @@ dmi_prodver(void) return NULL; } + return dmi_str_index(hdr, SYSINFO_VERSION); +} + +/* + * Return the product family from the DMI/SMBIOS + * System Info structure + * + * Returns NULL if not found + */ +const char * +dmi_prodfam(void) +{ + struct dmi_shdr *hdr; + + if ((hdr = dmi_shdr(DMI_SYSTEM_INFO)) == NULL) { + return NULL; + } + return dmi_str_index(hdr, SYSINFO_FAMILY); } @@ -198,6 +220,38 @@ dmi_cpu_manufact(void) return dmi_str_index(hdr, PROCINFO_MANUFACT); } +/* + * Return the CPU version string from the + * DMI/SMBIOS Processor Info structure + * + * Returns NULL if not found + */ +const char * +dmi_cpu_version(void) +{ + struct dmi_shdr *hdr; + + if ((hdr = dmi_shdr(DMI_PROCESSOR_INFO)) == NULL) { + return NULL; + } + + return dmi_str_index(hdr, PROCINFO_VERSION); +} + +static void +dmi_init_ctl(void) +{ + struct ctlfs_dev ctl; + char ctlname[] = "dmi"; + + /* Create '/ctl/dmi/board' */ + ctl.mode = 0444; + ctlfs_create_node(ctlname, &ctl); + ctl.devname = ctlname; + ctl.ops = &g_ctl_board_ident; + ctlfs_create_entry("board", &ctl); +} + static int dmi_init(void) { @@ -245,6 +299,7 @@ dmi_init(void) hdr = PTR_OFFSET(hdr, cur_nbytes); } + dmi_init_ctl(); return 0; } diff --git a/sys/dev/dmi/dmi_board.c b/sys/dev/dmi/dmi_board.c new file mode 100644 index 0000000..23709bd --- /dev/null +++ b/sys/dev/dmi/dmi_board.c @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/dmi.h> +#include <dev/dmi/dmi.h> +#include <dev/dmi/dmivar.h> +#include <fs/ctlfs.h> +#include <string.h> + +extern struct ctlops ctl_cpu_ident; + +static int +board_ctl_read(struct ctlfs_dev *cdp, struct sio_txn *sio) +{ + struct dmi_board board; + const char *cpu_manuf, *prodver; + const char *product, *vendor; + const char *cpu_ver, *p; + size_t len; + + if (cdp == NULL || sio == NULL) { + return -EINVAL; + } + /* Cannot copy zero bytes */ + if (sio->len == 0) { + return -EINVAL; + } + + /* Check offset and clamp length */ + if (sio->offset >= sizeof(board)) { + return 0; + } + if ((sio->offset + sio->len) > sizeof(board)) { + sio->len = sizeof(board); + } + + memset(&board, 0, sizeof(board)); + cpu_ver = dmi_cpu_version(); + if (cpu_ver != NULL) { + len = strlen(cpu_ver); + memcpy(board.cpu_version, cpu_ver, len); + } + + prodver = dmi_prodver(); + if (prodver != NULL) { + len = strlen(prodver); + memcpy(board.version, prodver, len); + } + + cpu_manuf = dmi_cpu_manufact(); + if (cpu_manuf != NULL) { + len = strlen(cpu_manuf); + memcpy(board.cpu_manuf, cpu_manuf, len); + } + + product = dmi_product(); + if (product != NULL) { + len = strlen(product); + memcpy(board.product, product, len); + } + + vendor = dmi_vendor(); + if (vendor != NULL) { + len = strlen(vendor); + memcpy(board.vendor, vendor, len); + } + + p = (char *)&board; + memcpy(sio->buf, &p[sio->offset], sio->len); + return sio->len; +} + +struct ctlops g_ctl_board_ident = { + .read = board_ctl_read, + .write = NULL +}; diff --git a/sys/include/dev/dmi/dmi.h b/sys/include/dev/dmi/dmi.h index d24397a..8b7030c 100644 --- a/sys/include/dev/dmi/dmi.h +++ b/sys/include/dev/dmi/dmi.h @@ -34,7 +34,9 @@ const char *dmi_vendor(void); const char *dmi_prodver(void); +const char *dmi_prodfam(void); const char *dmi_product(void); const char *dmi_cpu_manufact(void); +const char *dmi_cpu_version(void); #endif /* !_DMI_DMI_H_ */ diff --git a/sys/include/dev/dmi/dmivar.h b/sys/include/dev/dmi/dmivar.h new file mode 100644 index 0000000..e5da92f --- /dev/null +++ b/sys/include/dev/dmi/dmivar.h @@ -0,0 +1,41 @@ +/* + * 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 _DEV_DMIVAR_H_ +#define _DEV_DMIVAR_H_ + +#include <sys/types.h> +#include <sys/sio.h> +#include <fs/ctlfs.h> + +extern struct ctlops g_ctl_board_ident; + +int dmi_board_ctl_read(struct ctlfs_dev *cdp, struct sio_txn *sio); + +#endif /* !_DEV_DMIVAR_H_ */ diff --git a/sys/include/fs/ctlfs.h b/sys/include/fs/ctlfs.h index 90f42f0..29ae358 100644 --- a/sys/include/fs/ctlfs.h +++ b/sys/include/fs/ctlfs.h @@ -42,12 +42,10 @@ struct ctlops { /* * Ctlfs op arguments * - * @devname: Device name. - * @major: Device major - * @minor: Device minor. - * @mode: Access flags. * @devname [1]: Device name (node name) * @ctlname: [1]: Control name (node entry name) + * @ops: Callbacks / fs hooks + * @mode: Access flags. */ struct ctlfs_dev { union { diff --git a/sys/include/sys/dmi.h b/sys/include/sys/dmi.h new file mode 100644 index 0000000..a21cff6 --- /dev/null +++ b/sys/include/sys/dmi.h @@ -0,0 +1,63 @@ +/* + * 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_DMI_H_ +#define _SYS_DMI_H_ + +#if defined(_KERNEL) +#include <sys/types.h> +#else +#include <stdint.h> +#include <stddef.h> +#endif /* _KERNEL */ + +/* + * Provides board information through + * DMI. + * + * @cpu_version: CPU version string + * @cpu_manuf: CPU manufacturer string + * @product: Board product string + * @vendor: Board vendor string + * @version: Product version string + * + * If index 0 of any of the strings contain + * '\0', then they are unsupported/unused. + * + * XXX: Strings are null terminated + */ +struct dmi_board { + char cpu_version[64]; + char cpu_manuf[32]; + char product[32]; + char vendor[32]; + char version[32]; +}; + +#endif /* !_SYS_DMI_H_ */ diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 7fdf603..d8bf421 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -25,3 +25,4 @@ all: make -C whoami/ $(ARGS) make -C oasm/ $(ARGS) make -C oemu/ $(ARGS) + make -C dmidump/ $(ARGS) diff --git a/usr.bin/dmidump/Makefile b/usr.bin/dmidump/Makefile new file mode 100644 index 0000000..e9cd625 --- /dev/null +++ b/usr.bin/dmidump/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/dmidump: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/dmidump/dmidump.c b/usr.bin/dmidump/dmidump.c new file mode 100644 index 0000000..96d97bc --- /dev/null +++ b/usr.bin/dmidump/dmidump.c @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#include <sys/dmi.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +/* + * The kernel fills DMI structures to zero, + * if any of the fields are unset then p[0] + * will have a null terminator which tells + * us we should ignore it. + */ +static void +dmi_printfield(const char *name, const char *p) +{ + if (p[0] == '\0') { + return; + } + + printf("%s: %s\n", name, p); +} + +static void +dmi_dump_board(void) +{ + struct dmi_board board; + int fd; + + fd = open("/ctl/dmi/board", O_RDONLY); + if (fd < 0) { + printf("failed to open board control\n"); + return; + } + + read(fd, &board, sizeof(board)); + printf("** BOARD INFO **\n"); + dmi_printfield("CPU version", board.cpu_version); + dmi_printfield("CPU OEM", board.cpu_manuf); + dmi_printfield("product", board.product); + dmi_printfield("vendor", board.vendor); + dmi_printfield("version", board.version); + close(fd); +} + +int +main(int argc, char **argv) +{ + dmi_dump_board(); + return 0; +} diff --git a/usr.bin/mrow/Makefile b/usr.bin/mrow/Makefile index ae17849..d7c7ef4 100644 --- a/usr.bin/mrow/Makefile +++ b/usr.bin/mrow/Makefile @@ -3,4 +3,4 @@ include user.mk CFILES = $(shell find . -name "*.c") $(ROOT)/base/usr/bin/mrow: - gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) -lgfx diff --git a/usr.bin/mrow/mrow.c b/usr.bin/mrow/mrow.c index cad5530..1179f7e 100644 --- a/usr.bin/mrow/mrow.c +++ b/usr.bin/mrow/mrow.c @@ -27,9 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/mman.h> #include <sys/types.h> -#include <sys/fbdev.h> #include <fcntl.h> #include <stddef.h> #include <unistd.h> @@ -37,6 +35,8 @@ #include <time.h> #include <stdlib.h> #include <stdbool.h> +#include <libgfx/gfx.h> +#include <libgfx/draw.h> #define IS_ASCII(C) ((C) > 0 && (C) < 127) @@ -50,8 +50,8 @@ #define MIN_MOUSE_SPEED 1 #define PLAYER_SPEED 30 -#define SCR_WIDTH (fbattr.width) -#define SCR_HEIGHT (fbattr.height) +#define SCR_WIDTH (gfx_ctx.fbdev.width) +#define SCR_HEIGHT (gfx_ctx.fbdev.height) #define MAX_X (SCR_WIDTH - SPRITE_WIDTH) #define MAX_Y (SCR_HEIGHT - SPRITE_HEIGHT) @@ -59,7 +59,7 @@ #define HIT_BEEP_MSEC 50 #define HIT_BEEP_FREQ 600 -static struct fbattr fbattr; +static struct gfx_ctx gfx_ctx; static uint32_t *framep; static int beep_fd; static size_t hit_count = 0; @@ -77,26 +77,23 @@ struct mouse { uint8_t speed; }; -static inline size_t -pixel_index(uint32_t x, uint32_t y) -{ - return x + y * (fbattr.pitch / 4); -} - static void -draw_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t rgb) +draw_sprite(uint32_t x, uint32_t y, uint32_t color) { - for (uint32_t xpos = x; xpos < x + width; ++xpos) { - for (uint32_t ypos = y; ypos < y + height; ++ypos) { - framep[pixel_index(xpos, ypos)] = rgb; - } - } + struct gfx_shape sprite_shape = GFX_SHAPE_DEFAULT; + + sprite_shape.x = x; + sprite_shape.y = y; + sprite_shape.width = SPRITE_WIDTH; + sprite_shape.height = SPRITE_HEIGHT; + sprite_shape.color = color; + gfx_draw_shape(&gfx_ctx, &sprite_shape); } static void update_mouse(struct mouse *mouse) { - draw_rect(mouse->x, mouse->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + draw_sprite(mouse->x, mouse->y, GAME_BG); /* Move the mouse in the x direction */ if (mouse->x_inc) { @@ -128,7 +125,7 @@ update_mouse(struct mouse *mouse) mouse->y_inc = 1; } - draw_rect(mouse->x, mouse->y, SPRITE_WIDTH, SPRITE_HEIGHT, MOUSE_BG); + draw_sprite(mouse->x, mouse->y, MOUSE_BG); } static void @@ -178,8 +175,8 @@ mouse_collide(struct player *p, struct mouse *m) beep(HIT_BEEP_MSEC, HIT_BEEP_FREQ); /* Clear the sprites */ - draw_rect(m->x, m->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); - draw_rect(p->x, p->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + draw_sprite(m->x, m->y, GAME_BG); + draw_sprite(p->x, p->y, GAME_BG); m->x = 0; m->y = rand() % MAX_Y; @@ -216,8 +213,8 @@ game_loop(void) mouse.speed = MIN_MOUSE_SPEED; /* Draw player and mouse */ - draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, PLAYER_BG); - draw_rect(mouse.x, mouse.y, SPRITE_WIDTH, SPRITE_HEIGHT, MOUSE_BG); + draw_sprite(p.x, p.y, PLAYER_BG); + draw_sprite(mouse.x, mouse.y, MOUSE_BG); while (running) { if (mouse_collide(&p, &mouse)) { @@ -229,7 +226,7 @@ game_loop(void) update_mouse(&mouse); if (IS_ASCII(c)) { - draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + draw_sprite(p.x, p.y, GAME_BG); } switch (c) { @@ -263,42 +260,28 @@ game_loop(void) continue; } - draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, PLAYER_BG); + draw_sprite(p.x, p.y, PLAYER_BG); } } int main(void) { - int fb_fd, fbattr_fd, prot; - size_t fb_size; + int error; char c; - fb_fd = open("/dev/fb0", O_RDWR); - if (fb_fd < 0) { - return fb_fd; - } - - fbattr_fd = open("/ctl/fb0/attr", O_RDONLY); - if (fbattr_fd < 0) { - close(fb_fd); - return fbattr_fd; + error = gfx_init(&gfx_ctx); + if (error < 0) { + printf("failed to init libgfx\n"); + return error; } beep_fd = open("/dev/beep", O_WRONLY); - read(fbattr_fd, &fbattr, sizeof(fbattr)); - close(fbattr_fd); - - fb_size = fbattr.height * fbattr.pitch; - prot = PROT_READ | PROT_WRITE; - framep = mmap(NULL, fb_size, prot, MAP_SHARED, fb_fd, 0); - game_loop(); printf("\033[35;40mYOUR FINAL SCORE: %d\033[0m\n", hit_count); /* Cleanup */ close(beep_fd); - munmap(framep, fb_size); - close(fb_fd); + gfx_cleanup(&gfx_ctx); return 0; } |