summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--lib/libc/include/stdio.h2
-rw-r--r--lib/libc/src/hyra/spawn.c7
-rw-r--r--lib/libc/src/main.c7
-rw-r--r--lib/libc/src/stdio/snprintf.c15
-rw-r--r--lib/libc/src/stdio/vsnprintf.c6
-rw-r--r--sys/arch/amd64/amd64/proc_machdep.c3
-rw-r--r--sys/dev/cons/cons.c28
-rw-r--r--sys/dev/cons/cons_ansi.c3
-rw-r--r--sys/dev/pci/pci.c77
-rw-r--r--sys/fs/initramfs.c2
-rw-r--r--sys/include/dev/acpi/tables.h30
-rw-r--r--sys/include/dev/cons/cons.h1
-rw-r--r--sys/include/dev/pci/pci.h1
-rw-r--r--sys/include/sys/limits.h1
-rw-r--r--sys/include/sys/proc.h2
-rw-r--r--sys/include/sys/spawn.h2
-rw-r--r--sys/kern/exec_elf64.c1
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_exit.c7
-rw-r--r--sys/kern/kern_spawn.c53
-rw-r--r--usr.bin/Makefile1
-rw-r--r--usr.bin/mex/Makefile6
-rw-r--r--usr.bin/mex/mex.c105
-rw-r--r--usr.bin/osh/osh.c11
-rw-r--r--usr.sbin/install/install.c4
26 files changed, 337 insertions, 42 deletions
diff --git a/configure.ac b/configure.ac
index e8d4f38..3b89a07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([Hyra], [1.9], [ian@osmora.org])
+AC_INIT([Hyra], [2.0], [ian@osmora.org])
TARGET="amd64"
PROJECT_ROOT=`pwd`
diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h
index d94990b..88e66f6 100644
--- a/lib/libc/include/stdio.h
+++ b/lib/libc/include/stdio.h
@@ -77,6 +77,8 @@ size_t fwrite(const void *__restrict ptr, size_t size, size_t n, FILE *__restric
int vsnprintf(char *s, size_t size, const char *fmt, va_list ap);
int snprintf(char *s, size_t size, const char *fmt, ...);
+
+int printf(const char *__restrict fmt, ...);
int fputc(int c, FILE *stream);
int putchar(int c);
diff --git a/lib/libc/src/hyra/spawn.c b/lib/libc/src/hyra/spawn.c
index 227d8f7..b4c92ef 100644
--- a/lib/libc/src/hyra/spawn.c
+++ b/lib/libc/src/hyra/spawn.c
@@ -35,10 +35,13 @@
* Spawn a process
*
* @pathname: Path to executable.
+ * @argv: Argument vector
+ * @envp: Environment vector
* @flags: Spawn flags.
*/
pid_t
-spawn(const char *pathname, int flags)
+spawn(const char *pathname, char **argv, char **envp, int flags)
{
- return syscall(SYS_spawn, (uintptr_t)pathname, flags);
+ return syscall(SYS_spawn, (uintptr_t)pathname, (uintptr_t)argv,
+ (uintptr_t)envp, flags);
}
diff --git a/lib/libc/src/main.c b/lib/libc/src/main.c
index d16b93e..16e27ad 100644
--- a/lib/libc/src/main.c
+++ b/lib/libc/src/main.c
@@ -38,10 +38,15 @@ int
__libc_entry(uint64_t *ctx)
{
int status;
+ uint64_t argc;
+ char **argv;
+
+ argc = *(ctx++);
+ argv = (char **)((ctx++));
if ((status = __libc_stdio_init()) != 0) {
return status;
}
- return main(0, NULL);
+ return main(argc, argv);
}
diff --git a/lib/libc/src/stdio/snprintf.c b/lib/libc/src/stdio/snprintf.c
index e343b77..2387950 100644
--- a/lib/libc/src/stdio/snprintf.c
+++ b/lib/libc/src/stdio/snprintf.c
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <stdio.h>
#include <stddef.h>
+#include <unistd.h>
/* TODO FIXME: Use stdarg.h */
#define __va_start(ap, fmt) __builtin_va_start(ap, fmt)
@@ -46,3 +47,17 @@ snprintf(char *s, size_t size, const char *fmt, ...)
__va_end(ap);
return ret;
}
+
+int
+printf(const char *__restrict fmt, ...)
+{
+ char buf[512];
+ va_list ap;
+ int ret;
+
+ __va_start(ap, fmt);
+ ret = vsnprintf(buf, sizeof(buf), fmt, ap);
+ write(stdout->fd, buf, ret);
+ __va_end(ap);
+ return ret;
+}
diff --git a/lib/libc/src/stdio/vsnprintf.c b/lib/libc/src/stdio/vsnprintf.c
index 0e29600..24b2df6 100644
--- a/lib/libc/src/stdio/vsnprintf.c
+++ b/lib/libc/src/stdio/vsnprintf.c
@@ -123,6 +123,12 @@ vsnprintf(char *s, size_t size, const char *fmt, va_list ap)
num = __va_arg(ap, uint64_t);
itoa(num, num_buf, 16);
tmp_len = strlen(num_buf);
+ if (pad_width > 0) {
+ num_len = strlen(num_buf);
+ for (size_t i = num_len; i < pad_width; ++i)
+ printc(s, size, &off, '0');
+ pad_width = 0;
+ }
printstr(s, size, &off, num_buf + 2);
break;
case 's':
diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c
index 407adb1..aa8847a 100644
--- a/sys/arch/amd64/amd64/proc_machdep.c
+++ b/sys/arch/amd64/amd64/proc_machdep.c
@@ -40,7 +40,7 @@
#include <vm/map.h>
#include <string.h>
-void
+uintptr_t
md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog)
{
uintptr_t *sp = stack_top;
@@ -97,6 +97,7 @@ md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog)
STACK_PUSH(sp, argc);
tfp = &td->tf;
tfp->rsp = (uintptr_t)sp - VM_HIGHER_HALF;
+ return tfp->rsp;
}
void
diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c
index ce2b154..0735f11 100644
--- a/sys/dev/cons/cons.c
+++ b/sys/dev/cons/cons.c
@@ -65,7 +65,6 @@ static struct cdevsw cons_cdevsw;
static void cons_draw_cursor(struct cons_screen *scr, uint32_t color);
static int cons_handle_special(struct cons_screen *scr, char c);
-static void cons_clear_scr(struct cons_screen *scr, uint32_t bg);
static uint32_t
rgb_invert(uint32_t rgb)
@@ -191,22 +190,14 @@ cons_handle_special(struct cons_screen *scr, char c)
SHOW_CURSOR(scr);
return 0;
case ASCII_LF:
- HIDE_CURSOR(scr);
-
/* Are we past screen width? */
if (scr->ch_row >= scr->nrows - 1) {
cons_clear_scr(scr, scr->bg);
- cons_flush(scr);
- scr->ch_col = 0;
- scr->ch_row = 0;
-
- /* Update cursor */
- scr->curs_row = 0;
- scr->curs_col = 0;
- SHOW_CURSOR(scr);
return 0;
}
+ HIDE_CURSOR(scr);
+
/* Make a newline */
cons_flush(scr);
++scr->ch_row;
@@ -255,18 +246,25 @@ cons_draw_cursor(struct cons_screen *scr, uint32_t color)
* @scr: Screen to clear.
* @bg: Color to clear it to.
*/
-static void
+void
cons_clear_scr(struct cons_screen *scr, uint32_t bg)
{
struct fbdev fbdev = scr->fbdev;
- struct cons_buf *bp;
+
+ cons_flush(scr);
+ HIDE_CURSOR(scr);
+
+ scr->ch_col = 0;
+ scr->ch_row = 0;
+ scr->curs_col = 0;
+ scr->curs_row = 0;
for (size_t i = 0; i < fbdev.height * fbdev.pitch; ++i) {
scr->fb_mem[i] = bg;
}
- bp = scr->ob[scr->nrows - 1];
- bp->flags |= CONS_BUF_CLEAN;
+ SHOW_CURSOR(scr);
+
}
/*
diff --git a/sys/dev/cons/cons_ansi.c b/sys/dev/cons/cons_ansi.c
index 4403f9c..ab1f22a 100644
--- a/sys/dev/cons/cons_ansi.c
+++ b/sys/dev/cons/cons_ansi.c
@@ -90,8 +90,7 @@ ansi_feed(struct ansi_state *statep, char c)
return c;
case 2:
if (c == 'H') {
- cons_reset_cursor(&g_root_scr);
- ansi_reset(statep);
+ cons_clear_scr(&g_root_scr, g_root_scr.bg);
return ANSI_UPDATE_CURSOR;
}
break;
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 95fc5e2..9dfb90e 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -32,20 +32,31 @@
#include <sys/syslog.h>
#include <sys/errno.h>
#include <sys/spinlock.h>
+#include <sys/mmio.h>
#include <dev/pci/pci.h>
#include <dev/pci/pciregs.h>
+#include <dev/acpi/acpi.h>
+#include <dev/acpi/tables.h>
#include <machine/pci/pci.h>
#include <vm/dynalloc.h>
+#include <vm/vm.h>
#include <lib/assert.h>
#define pr_trace(fmt, ...) kprintf("pci: " fmt, ##__VA_ARGS__)
static TAILQ_HEAD(, pci_device) device_list;
static struct spinlock devlist_lock = {0};
+static struct acpi_mcfg *mcfg;
struct cam_hook {
+ /* PCI CAM */
pcireg_t(*cam_readl)(struct pci_device *dev, uint32_t off);
void(*cam_writel)(struct pci_device *dev, uint32_t off, pcireg_t val);
+
+ /* PCIe ECAM */
+ pcireg_t(*ecam_readl)(struct pci_device *dev, uint32_t off);
+ void(*ecam_writel)(struct pci_device *dev, uint32_t off, pcireg_t val);
+ void *ecam_base[1];
} cam_hook = { NULL };
static bool
@@ -129,6 +140,9 @@ pci_set_device_info(struct pci_device *dev)
dev->prog_if = PCIREG_PROGIF(classrev);
dev->hdr_type = (uint8_t)pci_readl(dev, PCIREG_HDRTYPE);
+ /* This is a PCIe device if it has CAP ID of 0x10 */
+ dev->pci_express = pci_get_cap(dev, 0x10) != 0;
+
/* Set type-specific data */
switch (dev->hdr_type & ~BIT(7)) {
case PCI_HDRTYPE_NORMAL:
@@ -157,6 +171,53 @@ pci_set_device_info(struct pci_device *dev)
static void
pci_scan_bus(uint8_t bus);
+static inline vaddr_t
+pcie_ecam_addr(struct pci_device *dev)
+{
+ vaddr_t base = (vaddr_t)cam_hook.ecam_base[0];
+
+ base += dev->bus << 20 |
+ dev->slot << 15 |
+ dev->func << 12;
+ return base;
+}
+
+static pcireg_t
+pcie_ecam_readl(struct pci_device *dev, uint32_t offset)
+{
+ vaddr_t address;
+
+ address = pcie_ecam_addr(dev);
+ address += (offset & ~3);
+ return mmio_read32((void *)address);
+}
+
+static void
+pcie_ecam_writel(struct pci_device *dev, uint32_t offset, pcireg_t val)
+{
+ vaddr_t address;
+
+ address = pcie_ecam_addr(dev);
+ address += (offset & ~3);
+ mmio_write32((void *)address, val);
+}
+
+static int
+pcie_init(struct acpi_mcfg_base *base)
+{
+ void *iobase;
+
+ pr_trace("[group %02d] @ bus [%02d - %02d]\n", base->seg_grpno,
+ base->bus_start, base->bus_end);
+ pr_trace("ecam @ %p\n", base->base_pa);
+
+ iobase = PHYS_TO_VIRT(base->base_pa);
+ cam_hook.ecam_base[0] = iobase;
+ cam_hook.ecam_writel = pcie_ecam_writel;
+ cam_hook.ecam_readl = pcie_ecam_readl;
+ return 0;
+}
+
/*
* Attempt to register a device.
*
@@ -283,8 +344,10 @@ pci_add_device(struct pci_device *dev)
pcireg_t
pci_readl(struct pci_device *dev, uint32_t offset)
{
- if (cam_hook.cam_readl == NULL) {
- return (pcireg_t)-1;
+ bool have_ecam = cam_hook.ecam_readl != NULL;
+
+ if (dev->pci_express && have_ecam) {
+ return cam_hook.ecam_readl(dev, offset);
}
return cam_hook.cam_readl(dev, offset);
@@ -293,7 +356,10 @@ pci_readl(struct pci_device *dev, uint32_t offset)
void
pci_writel(struct pci_device *dev, uint32_t offset, pcireg_t val)
{
- if (cam_hook.cam_writel == NULL) {
+ bool have_ecam = cam_hook.ecam_writel != NULL;
+
+ if (dev->pci_express && have_ecam) {
+ cam_hook.ecam_writel(dev, offset, val);
return;
}
@@ -306,6 +372,11 @@ pci_init(void)
size_t ndev;
TAILQ_INIT(&device_list);
+ mcfg = acpi_query("MCFG");
+ if (mcfg != NULL) {
+ pcie_init(&mcfg->base[0]);
+ }
+
cam_hook.cam_readl = md_pci_readl;
cam_hook.cam_writel = md_pci_writel;
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index b12a64b..c3f9b14 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -223,6 +223,8 @@ initramfs_read(struct vnode *vp, struct sio_txn *sio)
return -EIO;
if (sio->buf == NULL)
return -EIO;
+ if (sio->len > n->size)
+ sio->len = n->size;
src = n->data;
dest = sio->buf;
diff --git a/sys/include/dev/acpi/tables.h b/sys/include/dev/acpi/tables.h
index 5215c86..d190150 100644
--- a/sys/include/dev/acpi/tables.h
+++ b/sys/include/dev/acpi/tables.h
@@ -132,4 +132,34 @@ struct __packed acpi_hpet {
uint8_t page_protection;
};
+/*
+ * PCIe / ACPI MCFG base address description
+ * table.
+ *
+ * @base_pa: Enhanced configuration base [physical]
+ * @seg_grpno: PCI segment group number
+ * @bus_start: Host bridge bus start
+ * @bus_end: Host bridge bus end
+ */
+struct __packed acpi_mcfg_base {
+ uint64_t base_pa;
+ uint16_t seg_grpno;
+ uint8_t bus_start;
+ uint8_t bus_end;
+ uint32_t reserved;
+};
+
+/*
+ * PCIe / ACPI MCFG structure
+ *
+ * @hdr: ACPI header
+ * @reserved: Do not use
+ * @base: ECAM MMIO address list
+ */
+struct __packed acpi_mcfg {
+ struct acpi_header hdr;
+ uint32_t reserved[2];
+ struct acpi_mcfg_base base[1];
+};
+
#endif /* _ACPI_TABLES_H_ */
diff --git a/sys/include/dev/cons/cons.h b/sys/include/dev/cons/cons.h
index 9868493..7599dd5 100644
--- a/sys/include/dev/cons/cons.h
+++ b/sys/include/dev/cons/cons.h
@@ -67,6 +67,7 @@ struct cons_screen {
void cons_init(void);
void cons_expose(void);
void cons_update_color(struct cons_screen *scr, uint32_t fg, uint32_t bg);
+void cons_clear_scr(struct cons_screen *scr, uint32_t bg);
void cons_reset_color(struct cons_screen *scr);
void cons_reset_cursor(struct cons_screen *scr);
int cons_putch(struct cons_screen *scr, char c);
diff --git a/sys/include/dev/pci/pci.h b/sys/include/dev/pci/pci.h
index a4de162..144b500 100644
--- a/sys/include/dev/pci/pci.h
+++ b/sys/include/dev/pci/pci.h
@@ -62,6 +62,7 @@ struct pci_device {
uint8_t pci_subclass;
uint8_t prog_if;
uint8_t hdr_type;
+ uint8_t pci_express : 1;
uint8_t pri_bus;
uint8_t sec_bus;
diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h
index 198c963..f56958e 100644
--- a/sys/include/sys/limits.h
+++ b/sys/include/sys/limits.h
@@ -32,6 +32,7 @@
#define PATH_MAX 1024
#define SSIZE_MAX 32767
+#define ARG_MAX 4096
#define CHAR_BIT 8
#if defined(_KERNEL)
#define CPU_MAX 256
diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h
index 2f1470a..241d990 100644
--- a/sys/include/sys/proc.h
+++ b/sys/include/sys/proc.h
@@ -95,7 +95,7 @@ int md_spawn(struct proc *p, struct proc *parent, uintptr_t ip);
scret_t sys_spawn(struct syscall_args *scargs);
pid_t spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **newprocp);
-void md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog);
+uintptr_t md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog);
__dead void md_td_kick(struct proc *td);
int fork1(struct proc *cur, int flags, void(*ip)(void), struct proc **newprocp);
diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h
index 9d823db..0c54e4c 100644
--- a/sys/include/sys/spawn.h
+++ b/sys/include/sys/spawn.h
@@ -36,6 +36,6 @@
#define SPAWN_WAIT BIT(0)
#if !defined(_KERNEL)
-pid_t spawn(const char *pathname, int flags);
+pid_t spawn(const char *pathname, char **argv, char **envp, int flags);
#endif /* _KERNEL */
#endif /* !_SYS_SPAWN_H_ */
diff --git a/sys/kern/exec_elf64.c b/sys/kern/exec_elf64.c
index 3767b0b..987dda4 100644
--- a/sys/kern/exec_elf64.c
+++ b/sys/kern/exec_elf64.c
@@ -192,6 +192,7 @@ elf64_load(const char *pathname, struct proc *td, struct exec_prog *prog)
if ((status = elf64_verify(hdr)) != 0)
goto done;
+ memset(loadmap, 0, sizeof(loadmap));
pcbp = &td->pcb;
start = -1;
end = 0;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index b760912..2a53b8a 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -101,7 +101,7 @@ execve(struct proc *td, const struct execve_args *args)
stack_top = td->stack_base + (PROC_STACK_SIZE - 1);
/* Setup registers, signals and stack */
- md_td_stackinit(td, (void *)(stack_top + VM_HIGHER_HALF), &prog);
+ stack_top = md_td_stackinit(td, (void *)(stack_top + VM_HIGHER_HALF), &prog);
setregs(td, &prog, stack_top);
signals_init(td);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 6afae81..2f9e344 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -137,6 +137,10 @@ exit1(struct proc *td, int flags)
proc_reap(td);
}
+ if (td->data != NULL) {
+ dynfree(td->data);
+ }
+
/*
* Only free the process structure if we aren't
* being waited on, otherwise let it be so the
@@ -157,8 +161,6 @@ exit1(struct proc *td, int flags)
ci->curtd = NULL;
if (parent->pid == 0)
sched_enter();
- if (td->data == NULL)
- sched_enter();
parent->flags &= ~PROC_SLEEP;
sched_enter();
@@ -175,7 +177,6 @@ sys_exit(struct syscall_args *scargs)
{
struct proc *td = this_td();
- td->data = scargs->tf;
td->exit_status = scargs->arg0;
exit1(td, 0);
__builtin_unreachable();
diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c
index 60d8e22..a953a6e 100644
--- a/sys/kern/kern_spawn.c
+++ b/sys/kern/kern_spawn.c
@@ -45,10 +45,17 @@
#define pr_trace(fmt, ...) kprintf("spawn: " fmt, ##__VA_ARGS__)
#define pr_error(...) pr_trace(__VA_ARGS__)
+#define ARGVP_MAX (ARG_MAX / sizeof(void *))
+
static volatile size_t nthreads = 0;
+/*
+ * TODO: envp
+ */
struct spawn_args {
char path[PATH_MAX];
+ char argv_blk[ARG_MAX];
+ char *argv[ARGVP_MAX];
};
static inline void
@@ -67,7 +74,6 @@ spawn_thunk(void)
struct proc *cur;
struct execve_args execve_args;
struct spawn_args *args;
- char *argv[] = { NULL, NULL };
char *envp[] = { NULL };
cur = this_td();
@@ -76,13 +82,10 @@ spawn_thunk(void)
memset(pathbuf, 0, sizeof(pathbuf));
memcpy(pathbuf, path, strlen(path));
- argv[0] = (char *)pathbuf;
- execve_args.pathname = argv[0];
- execve_args.argv = argv;
+ execve_args.pathname = pathbuf;
+ execve_args.argv = (char **)&args->argv[0];
execve_args.envp = envp;
-
path = NULL;
- dynfree(args);
if (execve(cur, &execve_args) != 0) {
pr_error("execve failed, aborting\n");
@@ -211,19 +214,26 @@ get_child(struct proc *cur, pid_t pid)
/*
* arg0: The file /path/to/executable
- * arg1: Optional flags (`flags')
+ * arg1: Argv
+ * arg2: Envp (TODO)
+ * arg3: Optional flags (`flags')
*/
scret_t
sys_spawn(struct syscall_args *scargs)
{
struct spawn_args *args;
- const char *u_path;
+ char *path;
+ const char *u_path, **u_argv;
+ const char *u_p = NULL;
struct proc *td;
int flags, error;
+ size_t len, bytes_copied = 0;
+ size_t argv_i = 0;
td = this_td();
- flags = scargs->arg1;
u_path = (const char *)scargs->arg0;
+ u_argv = (const char **)scargs->arg1;
+ flags = scargs->arg3;
args = dynalloc(sizeof(*args));
if (args == NULL) {
@@ -236,5 +246,30 @@ sys_spawn(struct syscall_args *scargs)
return error;
}
+ memset(args->argv, 0, ARG_MAX);
+ for (size_t i = 0; i < ARG_MAX - 1; ++i) {
+ error = copyin(&u_argv[argv_i], &u_p, sizeof(u_p));
+ if (error < 0) {
+ dynfree(args);
+ return error;
+ }
+ if (u_p == NULL) {
+ args->argv[argv_i++] = NULL;
+ break;
+ }
+
+ path = &args->argv_blk[i];
+ error = copyinstr(u_p, path, ARG_MAX - bytes_copied);
+ if (error < 0) {
+ dynfree(args);
+ return error;
+ }
+
+ args->argv[argv_i++] = &args->argv_blk[i];
+ len = strlen(path);
+ bytes_copied += (len + 1);
+ i += len;
+ }
+
return spawn(td, spawn_thunk, args, flags, NULL);
}
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
index 80eafc7..779aacd 100644
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -10,3 +10,4 @@ all:
make -C fetch/ $(ARGS)
make -C kfgwm/ $(ARGS)
make -C time/ $(ARGS)
+ make -C mex/ $(ARGS)
diff --git a/usr.bin/mex/Makefile b/usr.bin/mex/Makefile
new file mode 100644
index 0000000..6c0db59
--- /dev/null
+++ b/usr.bin/mex/Makefile
@@ -0,0 +1,6 @@
+include user.mk
+
+CFILES = $(shell find . -name "*.c")
+
+$(ROOT)/base/usr/bin/mex:
+ gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS)
diff --git a/usr.bin/mex/mex.c b/usr.bin/mex/mex.c
new file mode 100644
index 0000000..7e6f8aa
--- /dev/null
+++ b/usr.bin/mex/mex.c
@@ -0,0 +1,105 @@
+/*
+ * 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 <unistd.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+
+#define LINE_LEN 16
+
+static void
+dump_line(const char *line, size_t len)
+{
+ /* The amount of bytes we write */
+ const uint8_t BYTE_COUNT = 2;
+
+ for (size_t i = 0; i < LINE_LEN; ++i) {
+ if (i < len) {
+ printf("%02x", line[i] & 0xFF);
+ } else {
+ printf(" ");
+ }
+
+ /* Put spacing between bytes */
+ if (((i + 1) % BYTE_COUNT) == 0) {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+ for (size_t i = 0; i < len; ++i) {
+ if (line[i] > 31 && line[i] < 127) {
+ printf("%c", line[i]);
+ } else {
+ printf(".");
+ }
+ }
+
+ printf("\n");
+}
+
+static void
+dump_file(int fd)
+{
+ char buf[LINE_LEN];
+ ssize_t count;
+ size_t offset = 0;
+
+ for (;;) {
+ count = read(fd, buf, sizeof(char) * LINE_LEN);
+ if (count <= 0) {
+ break;
+ }
+
+ printf("%08x: ", offset);
+ offset += LINE_LEN;
+ dump_line(buf, count);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+
+ if (argc < 2) {
+ printf("mex: usage: mex <filename>\n");
+ return -1;
+ }
+
+ if ((fd = open(argv[1], O_RDONLY)) < 0) {
+ printf("mex: failed to open input\n");
+ return fd;
+ }
+
+ dump_file(fd);
+ return 0;
+}
diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c
index 93ac876..db8865d 100644
--- a/usr.bin/osh/osh.c
+++ b/usr.bin/osh/osh.c
@@ -56,6 +56,7 @@
"kfg - Start up kfgwm\n" \
"bell - Toggle backspace bell\n" \
"time - Get the current time\n" \
+ "clear - Clear the screen\n" \
"exit - Exit the shell"
#define PROMPT "[root::osmora]~ "
@@ -106,6 +107,12 @@ cmd_echo(int argc, char *argv[])
}
static void
+cmd_clear(int argc, char *argv[])
+{
+ fputs("\033[H", stdout);
+}
+
+static void
cmd_bell(int argc, char *argv[])
{
const char *usage_str = "usage: bell [on/off]";
@@ -219,6 +226,7 @@ static int
cmd_run(const char *input, int argc, char *argv[])
{
char bin_path[256];
+ char *envp[1] = { NULL };
int error;
snprintf(bin_path, sizeof(bin_path), "/usr/bin/%s", input);
@@ -228,7 +236,7 @@ cmd_run(const char *input, int argc, char *argv[])
return -1;
}
- if ((error = spawn(bin_path, SPAWN_WAIT)) < 0) {
+ if ((error = spawn(bin_path, argv, envp, SPAWN_WAIT)) < 0) {
return error;
}
@@ -242,6 +250,7 @@ struct builtin_cmd cmds[] = {
{"reboot",cmd_reboot},
{"shutdown", cmd_shutdown},
{"bell", cmd_bell},
+ {"clear", cmd_clear},
{NULL, NULL}
};
diff --git a/usr.sbin/install/install.c b/usr.sbin/install/install.c
index 5cedc06..91f75df 100644
--- a/usr.sbin/install/install.c
+++ b/usr.sbin/install/install.c
@@ -82,6 +82,8 @@ installer_clearscr(uint32_t color, bool setattr)
static void
pre_installer(void)
{
+ char *argv[] = { "/usr/bin/osh", NULL };
+ char *envp[] = { NULL };
char c;
puts("[S]hell/[I]nstall");
@@ -90,7 +92,7 @@ pre_installer(void)
if (c == 's') {
puts("\033[0m");
installer_clearscr(0x000000, false);
- spawn("/usr/bin/osh", SPAWN_WAIT);
+ spawn(argv[0], argv, envp, SPAWN_WAIT);
installer_clearscr(INSTALLER_BG, true);
break;
} else if (c == 'i') {