aboutsummaryrefslogtreecommitdiff
path: root/src/init/ps1
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-07-07 13:22:53 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-11-11 00:08:15 +0100
commit7861a52adf92a083bb2aed4c35f98d8035dce032 (patch)
tree28cd3c40e4c878f730f5df3c1d93bdf91af490c3 /src/init/ps1
parent7fc48e9216ff809da5f8055a50b0be17628ef1df (diff)
downloadwnix-7861a52adf92a083bb2aed4c35f98d8035dce032.tar.gz
Setup project skeleton
Diffstat (limited to 'src/init/ps1')
-rw-r--r--src/init/ps1/CMakeLists.txt37
-rw-r--r--src/init/ps1/private_include/init/ps1/types.h40
-rw-r--r--src/init/ps1/src/CMakeLists.txt23
-rw-r--r--src/init/ps1/src/boot.c251
-rw-r--r--src/init/ps1/src/globalvars.c21
-rw-r--r--src/init/ps1/src/port.c30
-rw-r--r--src/init/ps1/src/run.c27
-rw-r--r--src/init/ps1/src/time.c47
8 files changed, 476 insertions, 0 deletions
diff --git a/src/init/ps1/CMakeLists.txt b/src/init/ps1/CMakeLists.txt
new file mode 100644
index 0000000..21df5d7
--- /dev/null
+++ b/src/init/ps1/CMakeLists.txt
@@ -0,0 +1,37 @@
+# wnix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(init_ps1)
+add_subdirectory(src)
+target_include_directories(init_ps1 PRIVATE private_include)
+target_link_libraries(init_ps1
+ PUBLIC
+ c
+ init
+ PRIVATE
+ aio
+ bin
+ drv_ps1_bios
+ drv_ps1_cpu
+ drv_ps1_irq
+ drv_ps1_rcnt
+ drv_ps1_time
+ iso9660
+ kprintf
+ loop
+ net
+ state
+)
diff --git a/src/init/ps1/private_include/init/ps1/types.h b/src/init/ps1/private_include/init/ps1/types.h
new file mode 100644
index 0000000..66702d1
--- /dev/null
+++ b/src/init/ps1/private_include/init/ps1/types.h
@@ -0,0 +1,40 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef INIT_PS1_TYPES_H
+#define INIT_PS1_TYPES_H
+
+#include <aio.h>
+#include <sys/stat.h>
+#include <time.h>
+
+struct init_ps1
+{
+ struct aio *aio;
+ struct stat *sb;
+ unsigned retries;
+ const char *path;
+ struct timespec last_retry;
+ int (*next)(struct init_ps1 *);
+ int (*success)(struct init_ps1 *);
+ int (*retry)(struct init_ps1 *);
+};
+
+extern struct init_ps1 init_ps1;
+
+#endif
diff --git a/src/init/ps1/src/CMakeLists.txt b/src/init/ps1/src/CMakeLists.txt
new file mode 100644
index 0000000..68dab00
--- /dev/null
+++ b/src/init/ps1/src/CMakeLists.txt
@@ -0,0 +1,23 @@
+# wnix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(init_ps1 PRIVATE
+ boot.c
+ globalvars.c
+ port.c
+ run.c
+ time.c
+)
diff --git a/src/init/ps1/src/boot.c b/src/init/ps1/src/boot.c
new file mode 100644
index 0000000..062078c
--- /dev/null
+++ b/src/init/ps1/src/boot.c
@@ -0,0 +1,251 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+#include <aio.h>
+#include <bin.h>
+#include <iso9660.h>
+#include <kprintf.h>
+#include <loop.h>
+#include <net.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <state.h>
+#include <time.h>
+
+struct boot
+{
+ struct aio *aio;
+ struct init_ps1 *p;
+};
+
+enum {RETRIES = 5};
+static const char serial[] = "/dev/ttyS0";
+
+static int retry_cd(struct init_ps1 *);
+
+static int wait_retry(struct init_ps1 *const p)
+{
+ struct timespec ts;
+ const time_t last = p->last_retry.tv_sec, timeout = 5;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts))
+ return -1;
+ else if (ts.tv_sec - last >= timeout)
+ p->next = p->retry;
+
+ return 0;
+}
+
+static int stat_done(const enum state s, void *const args)
+{
+ int ret = 0;
+ struct init_ps1 *const p = args;
+
+ if (s)
+ {
+ struct timespec ts;
+
+ if (!--p->retries || clock_gettime(CLOCK_REALTIME, &ts))
+ {
+ ret = -1;
+ goto end;
+ }
+
+ p->last_retry = ts;
+ p->next = wait_retry;
+ }
+ else
+ {
+ p->next = p->success;
+ kprintf("Successfully initialized %s (took %u attempts)\n",
+ p->path, RETRIES - p->retries + 1);
+ }
+
+end:
+ loop_rm_aio(p->aio);
+ aio_free(p->aio);
+ free(p->sb);
+ return ret;
+}
+
+static int mount_done(const enum state state, void *const args)
+{
+ struct boot *const b = args;
+
+ if (loop_rm_aio(b->aio))
+ return -1;
+
+ aio_free(b->aio);
+ free(b);
+
+ if (state)
+ kprintf("Failed to mount ISO9660 filesystem\n");
+ else
+ {
+ const char *const args[] = {NULL};
+
+ kprintf("ISO9660 filesystem mounted successfully\n");
+ kprintf("Opening second-stage initd\n");
+
+ /* TODO: create symbolic from /mnt/cdrom/bin to /bin */
+ return bin_exec("/mnt/cdrom/bin/initd", args, 0, 0);
+ }
+
+ return 0;
+}
+
+static int mount_cd(struct init_ps1 *const p)
+{
+ struct aio *aio = NULL;
+ struct boot *const b = malloc(sizeof *b);
+
+ if (!b)
+ goto failure;
+
+ const struct aio_mount fm =
+ {
+ .mount =
+ {
+ .src = "/dev/cd0",
+ .tgt = "/mnt/cdrom",
+ .mode = 0755
+ },
+
+ .type = "iso9660"
+ };
+
+ const struct aio_done d =
+ {
+ .args = b,
+ .f = mount_done
+ };
+
+ if (!(aio = aio_mount(&fm, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ p->next = NULL;
+ *b = (const struct boot){.aio = aio, .p = p};
+ kprintf("Mounting ISO9660 filesystem from %s to %s\n",
+ fm.mount.src, fm.mount.tgt);
+ return 0;
+
+failure:
+ kprintf("Failed to mount ISO9660 filesystem\n");
+ aio_free(aio);
+ free(b);
+ return -1;
+}
+
+static int retry_cd(struct init_ps1 *const p)
+{
+ static const char path[] = "/dev/cd0";
+ struct aio *aio = NULL;
+ struct stat *const sb = malloc(sizeof *sb);
+
+ if (!sb)
+ goto failure;
+
+ const struct fs_stat s = {.path = path, .sb = sb};
+ const struct aio_done d = {.f = stat_done, .args = p};
+ const unsigned retries = p->retries;
+
+ if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ *p = (const struct init_ps1)
+ {
+ .aio = aio,
+ .sb = sb,
+ .path = path,
+ .retries = retries,
+ .success = mount_cd,
+ .last_retry = {.tv_sec = (time_t)-1}
+ };
+
+ p->next = NULL;
+ kprintf("Initializing CD-ROM to %s (attempt %u)\n", path,
+ RETRIES - p->retries + 1);
+ return 0;
+
+failure:
+ free(aio);
+ free(sb);
+ return -1;
+}
+
+static int init_net(struct init_ps1 *const p)
+{
+ if (net_init(serial))
+ return -1;
+
+ p->next = retry_cd;
+ return 0;
+}
+
+static int retry_serial(struct init_ps1 *const p)
+{
+ struct aio *aio = NULL;
+ struct stat *const sb = malloc(sizeof *sb);
+
+ if (!sb)
+ goto failure;
+
+ const struct fs_stat s = {.path = serial, .sb = sb};
+ const struct aio_done d = {.f = stat_done, .args = p};
+ const unsigned retries = p->retries;
+
+ if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ *p = (const struct init_ps1)
+ {
+ .aio = aio,
+ .sb = sb,
+ .path = serial,
+ .retries = retries,
+ .success = init_net,
+ .last_retry = {.tv_sec = (time_t)-1}
+ };
+
+ p->next = NULL;
+ kprintf("Initializing serial device to %s (attempt %u)\n", serial,
+ RETRIES - p->retries + 1);
+ return 0;
+
+failure:
+ free(aio);
+ free(sb);
+ return -1;
+}
+
+int init_port_boot(void)
+{
+ if (iso9660_register())
+ return -1;
+
+ init_ps1 = (const struct init_ps1)
+ {
+ .retries = RETRIES,
+ .next = retry_serial
+ };
+
+ return 0;
+}
diff --git a/src/init/ps1/src/globalvars.c b/src/init/ps1/src/globalvars.c
new file mode 100644
index 0000000..fcf6a6c
--- /dev/null
+++ b/src/init/ps1/src/globalvars.c
@@ -0,0 +1,21 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init/ps1/types.h>
+
+struct init_ps1 init_ps1;
diff --git a/src/init/ps1/src/port.c b/src/init/ps1/src/port.c
new file mode 100644
index 0000000..9bc2a8e
--- /dev/null
+++ b/src/init/ps1/src/port.c
@@ -0,0 +1,30 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <drv/ps1/bios.h>
+#include <drv/ps1/irq.h>
+
+int init_port(void)
+{
+ EnterCriticalSection();
+ SetConf(16, 1, (void *)0x801ff800);
+ ExitCriticalSection();
+
+ return drv_ps1_irq_init();
+}
diff --git a/src/init/ps1/src/run.c b/src/init/ps1/src/run.c
new file mode 100644
index 0000000..bc4b645
--- /dev/null
+++ b/src/init/ps1/src/run.c
@@ -0,0 +1,27 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+
+int init_port_run(void)
+{
+ struct init_ps1 *const p = &init_ps1;
+
+ return p->next ? p->next(p) : 0;
+}
diff --git a/src/init/ps1/src/time.c b/src/init/ps1/src/time.c
new file mode 100644
index 0000000..1978945
--- /dev/null
+++ b/src/init/ps1/src/time.c
@@ -0,0 +1,47 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+#include <drv/ps1/bios.h>
+#include <drv/ps1/cpu.h>
+#include <drv/ps1/rcnt.h>
+#include <drv/ps1/time.h>
+#include <time.h>
+
+int init_time(void)
+{
+ struct timespec ts;
+ const union drv_ps1_rcnt_cfg cfg =
+ {
+ .bits =
+ {
+ .reset = 1,
+ .repeat = 1,
+ .irq_tgt = 1,
+ .clocksrc = 3
+ }
+ };
+
+ if (clock_getres(CLOCK_REALTIME, &ts))
+ return -1;
+
+ const uint16_t target = (DRV_PS1_CPU_F / 8) / (ts.tv_nsec / 1000);
+
+ return drv_ps1_rcnt_init(DRV_PS1_RCNT2, target, &cfg, drv_ps1_time_tick);
+}