summaryrefslogtreecommitdiff
path: root/src/kernel/drive.c
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2021-06-21 17:47:13 -0400
committerBenji Dial <benji6283@gmail.com>2021-06-21 17:47:13 -0400
commitf57e2eabe0a10c9732c83532e01654a499fb8dcf (patch)
treecbf91a23fcdd65e0ea7ed55b0940ca7042d59bef /src/kernel/drive.c
parent83835306d57461205a7bcfef9f4c3e06bc504006 (diff)
downloadportland-os-f57e2eabe0a10c9732c83532e01654a499fb8dcf.tar.gz
many, many changes; settings is broken
Diffstat (limited to 'src/kernel/drive.c')
-rw-r--r--src/kernel/drive.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/kernel/drive.c b/src/kernel/drive.c
index bc1c67d..6a1d12e 100644
--- a/src/kernel/drive.c
+++ b/src/kernel/drive.c
@@ -1,5 +1,7 @@
#include "drive.h"
#include "panic.h"
+#include "pmap.h"
+#include "util.h"
#include "fat.h"
#include "log.h"
@@ -40,6 +42,7 @@ static inline void determine_fs(struct drive *d) {
if (try_fat_init_drive(d))
return;
+ d->mapped_to = 0;
d->fs_type = "Unknown";
d->get_file = &unknown_get_file;
d->free_file = &unknown_no_call;
@@ -58,7 +61,83 @@ static inline void determine_fs(struct drive *d) {
//do not need to make ready or done
void commit_drive(struct drive data) {
determine_fs(&data);
+ data.mapped_to = 0;
drives[n_drives] = data;
data.done(drives + n_drives);
++n_drives;
+}
+
+void map_path(const char *full, struct drive **d, const char **path) {
+ *d = 0;
+ *path = 0;
+
+ switch (full[0]) {
+ case '/':
+ for (struct drive *i = drives; i < drives + n_drives; ++i) {
+ if (!i->mapped_to)
+ continue;
+ uint32_t j = 0;
+ while (1) {
+ if (!i->mapped_to[j]) {
+ if (!*path || (j >= *path - full)) {
+ *path = full + j + 1;
+ *d = i;
+ }
+ break;
+ }
+ else if (i->mapped_to[j] != full[j + 1])
+ break;
+ ++j;
+ }
+ }
+ return;
+
+ uint32_t id;
+ case ':':
+ id = 0;
+ for (uint32_t i = 1; i < 9; ++i) {
+ id *= 16;
+ const char c = full[i];
+ if ((c >= '0') && (c <= '9'))
+ id += c - '0';
+ else if ((c >= 'a') && (c <= 'f'))
+ id += c - 'a' + 10;
+ else
+ return;
+ }
+ if (full[9] != ':')
+ return;
+ for (struct drive *i = drives; i < drives + n_drives; ++i)
+ if (i->uid == id) {
+ *d = i;
+ *path = full + 10;
+ return;
+ }
+ }
+}
+
+void map_drives() {
+ for (struct drive *d = drives; d < drives + n_drives; ++d) {
+ file_id_t fid = d->get_file(d, "_fstab");
+ if (!fid)
+ continue;
+
+ const uint32_t len = d->get_file_length(d, fid);
+ void *fstab = allocate_kernel_pages(len / 512 + 1);
+ fmcpy(fstab, d, fid, 0, len);
+ d->free_file(d, fid);
+ const uint32_t n_entries = *(uint32_t *)fstab;
+
+ uint32_t next_id = *(uint32_t *)(fstab + 4);
+ fstab += 8;
+ for (uint32_t i = 0; i < n_entries; ++i) {
+ for (struct drive *dd = drives; dd < drives + n_drives; ++dd)
+ if (dd->uid == next_id)
+ dd->mapped_to = fstab + 4;
+ const uint32_t plen = *(uint32_t *)fstab;
+ next_id = *(uint32_t *)(fstab + 4 + plen);
+ *(char *)(fstab + 4 + plen) = '\0';
+ fstab += 8 + plen;
+ }
+ }
} \ No newline at end of file