+# -*- makefile -*-
+
SHELL = /bin/sh
-VPATH = $(TOP_SRCDIR)/threads:$(TOP_SRCDIR)/devices:$(TOP_SRCDIR)/lib
+VPATH := $(TOP_SRCDIR)/threads
+VPATH := $(VPATH):$(TOP_SRCDIR)/devices
+VPATH := $(VPATH):$(TOP_SRCDIR)/lib
+VPATH := $(VPATH):$(TOP_SRCDIR)/filesys
-include *.d
ASFLAGS = $(INCLUDES) $(DEFINES)
# Core kernel.
-THREADS_SRC = start.S # Must be first.
-THREADS_SRC += init.c # Start-up code.
-THREADS_SRC += thread.c # Thread management core.
-THREADS_SRC += switch.S # Thread switch routine.
+THREADS_SRC = start.S # Must be linked first.
+THREADS_SRC += init.c # Start-up code.
+THREADS_SRC += thread.c # Thread management core.
+THREADS_SRC += switch.S # Thread switch routine.
THREADS_SRC += interrupt.c # Interrupt core.
THREADS_SRC += intr-stubs.S # Interrupt stubs.
-THREADS_SRC += synch.c # Synchronization.
-THREADS_SRC += palloc.c # Page allocator.
-THREADS_SRC += malloc.c # Subpage allocator.
+THREADS_SRC += synch.c # Synchronization.
+THREADS_SRC += palloc.c # Page allocator.
+THREADS_SRC += malloc.c # Subpage allocator.
# Device driver code.
-DEVICES_SRC = timer.c # Timer device.
-DEVICES_SRC += kbd.c # Keyboard device.
-DEVICES_SRC += vga.c # Video device.
-DEVICES_SRC += serial.c # Serial port device.
+DEVICES_SRC = timer.c # Timer device.
+DEVICES_SRC += kbd.c # Keyboard device.
+DEVICES_SRC += vga.c # Video device.
+DEVICES_SRC += serial.c # Serial port device.
# Library code.
LIB_SRC = debug.c # Debug helpers.
LIB_SRC += random.c # Pseudo-random numbers.
LIB_SRC += list.c # Doubly-linked lists.
LIB_SRC += bitmap.c # Bitmaps.
+LIB_SRC += backdoor.c # Backdoor IPC.
+
+# Filesystem code.
+FILESYS_SRC = filesys.c # Filesystem core.
+FILESYS_SRC += file.c # Individual files.
+FILESYS_SRC += filesys-stub.c # Stub helper code.
# Objects.
OBJECTS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(SOURCES)))
$< > $@.tmp && mv $@.tmp $@
kernel.o: $(OBJECTS)
- echo $(OBJECTS)
ld -T $(TOP_SRCDIR)/threads/kernel.lds -o $@ $^ \
`$(CC) -print-libgcc-file-name`
--- /dev/null
+all:
+%:
+ $(MAKE) -C build $@
--- /dev/null
+TOP_SRCDIR = ../..
+DEFINES = -DFILESYS_STUB
+SOURCES = $(THREADS_SRC) $(DEVICES_SRC) $(LIB_SRC) $(FILESYS_SRC)
+INCLUDES = -I$(TOP_SRCDIR)/threads -I$(TOP_SRCDIR)/devices \
+ -I$(TOP_SRCDIR)/lib -I$(TOP_SRCDIR)/filesys
+
+include ../../Makefile.inc
+
--- /dev/null
+#include "file.h"
+
+#ifdef FILESYS_STUB
+off_t
+file_read (struct file *file, void *buffer, off_t size)
+{
+ int32_t retval = -1;
+ filesys_stub_send ("s'read' i i", (int32_t) file, (int32_t) size);
+ filesys_stub_receive ("s'read' i", &retval);
+ if (retval > 0)
+ {
+ if (!filesys_stub_receive ("B", buffer, (size_t) retval))
+ retval = -1;
+ }
+ return retval;
+}
+
+off_t
+file_write (struct file *file, const void *buffer, off_t size)
+{
+ int32_t retval = -1;
+ filesys_stub_send ("s'write' i B", (int32_t) file, buffer, (size_t) size);
+ filesys_stub_receive ("s'write' i", &retval);
+ return retval;
+}
+
+off_t
+file_length (struct file *file)
+{
+ int32_t length = -1;
+ filesys_stub_send ("s'length' i", (int32_t) file);
+ filesys_stub_receive ("s'length' i", &length);
+ return length;
+}
+
+void
+file_seek (struct file *file, off_t pos)
+{
+ filesys_stub_send ("s'seek' i i", (int32_t) file, (int32_t) pos);
+ filesys_stub_receive ("s'seek'");
+}
+
+off_t
+file_tell (struct file *file)
+{
+ int32_t pos = -1;
+ filesys_stub_send ("s'tell' i", (int32_t) file);
+ filesys_stub_receive ("s'tell'", &pos);
+ return pos;
+}
+#endif /* FILESYS_STUB */
--- /dev/null
+#ifndef HEADER_FILE_H
+#define HEADER_FILE_H 1
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef int32_t off_t;
+
+struct file;
+off_t file_read (struct file *, void *, off_t);
+off_t file_write (struct file *, const void *, off_t);
+off_t file_length (struct file *);
+void file_seek (struct file *, off_t);
+off_t file_tell (struct file *);
+
+#endif /* file.h */
--- /dev/null
+#include "filesys-stub.h"
+#include <stdarg.h>
+#include "backdoor.h"
+#include "debug.h"
+#include "io.h"
+
+static void
+out_byte (uint8_t byte, void *aux UNUSED)
+{
+ outb (0x8901, byte);
+}
+
+void
+filesys_stub_send (const char *types, ...)
+{
+ va_list args;
+
+ va_start (args, types);
+ backdoor_vmarshal (types, args, out_byte, NULL);
+ va_end (args);
+}
+
+static bool
+in_byte (uint8_t *byte, void *aux UNUSED)
+{
+ *byte = inb (0x8901);
+ return true;
+}
+
+void
+filesys_stub_receive (const char *types, ...)
+{
+ va_list args;
+
+ va_start (args, types);
+ backdoor_vunmarshal (types, args, in_byte, NULL);
+ va_end (args);
+}
--- /dev/null
+#ifndef HEADER_FILESYS_STUB_H
+#define HEADER_FILESYS_STUB_H 1
+
+void filesys_stub_send (const char *types, ...);
+void filesys_stub_receive (const char *types, ...);
+
+#endif /* filesys-stub.h */
--- /dev/null
+#include "filesys.h"
+
+#ifdef FILESYS_STUB
+void
+filesys_init (bool reformat)
+{
+ if (reformat)
+ printk ("filesystem stubs don't support formatting\n");
+}
+
+bool
+filesys_create (const char *name)
+{
+ bool success = false;
+ filesys_stub_send ("s'create' s", name);
+ filesys_stub_receive ("s'create' b", &success);
+ return success;
+}
+
+struct file *
+filesys_open (const char *name)
+{
+ int32_t handle = -1;
+ filesys_stub_stub ("s'open' i", name);
+ filesys_stub_receive ("s'open' i", &handle);
+ return handle == -1 ? NULL : (struct file *) handle;
+}
+
+bool
+filesys_remove (const char *name)
+{
+ bool success = false;
+ filesys_stub_send ("s'create' s", name);
+ filesys_stub_receive ("s'create' b", &success);
+ return success;
+}
+#endif /* FILESYS_STUB */
--- /dev/null
+#ifndef HEADER_FILESYS_H
+#define HEADER_FILESYS_H 1
+
+#include <stdbool.h>
+
+void filesys_init (bool reformat);
+bool filesys_create (const char *name);
+struct file *filesys_open (const char *name);
+bool filesys_remove (const char *name);
+
+#endif /* filesys.h */
--- /dev/null
+#include "backdoor.h"
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+marshal_int32 (int32_t value, void (*out) (uint8_t, void *aux), void *aux)
+{
+ out ((value >> 24) & 0xff, aux);
+ out ((value >> 16) & 0xff, aux);
+ out ((value >> 8) & 0xff, aux);
+ out (value & 0xff, aux);
+}
+
+static void
+marshal_bytes (const void *buffer, size_t cnt,
+ void (*out) (uint8_t, void *aux), void *aux)
+{
+ const uint8_t *p = buffer;
+ size_t i;
+
+ for (i = 0; i < cnt; i++)
+ out (p[i], aux);
+}
+
+enum backdoor_error
+backdoor_vmarshal (const char *types, va_list args,
+ void (*out) (uint8_t, void *aux), void *aux)
+{
+ const char *p = types;
+
+ for (;;)
+ {
+ /* Find next type character. */
+ while (*p == ' ')
+ p++;
+ if (*p == '\0')
+ return BACKDOOR_OK;
+
+ out (*p, aux);
+ switch (*p++)
+ {
+ case 's':
+ if (*p == '\'')
+ {
+ const char *end = strchr (++p, '\'');
+ marshal_int32 (end - p, out, aux);
+ marshal_bytes (p, end - p, out, aux);
+ p = end + 1;
+ }
+ else
+ {
+ const char *s = va_arg (args, const char *);
+ marshal_int32 (strlen (s), out, aux);
+ marshal_bytes (s, strlen (s), out, aux);
+ }
+ break;
+
+ case 'i':
+ marshal_int32 (va_arg (args, int32_t), out, aux);
+ break;
+
+ case 'B':
+ {
+ const void *buffer = va_arg (args, const void *);
+ size_t size = va_arg (args, size_t);
+ marshal_int32 (size, out, aux);
+ marshal_bytes (buffer, size, out, aux);
+ }
+ break;
+
+ case 'b':
+ marshal_int32 (va_arg (args, int), out, aux);
+ break;
+
+ default:
+ return BACKDOOR_BAD_TYPE;
+ }
+ }
+}
+
+static bool
+unmarshal_int32 (int32_t *value,
+ bool (*in) (uint8_t *, void *aux), void *aux)
+{
+ int32_t tmp;
+ int i;
+
+ tmp = 0;
+ for (i = 0; i < 4; i++)
+ {
+ uint8_t b;
+ if (!in (&b, aux))
+ return false;
+
+ tmp = (tmp << 8) | b;
+ }
+ *value = tmp;
+ return true;
+}
+
+static bool
+unmarshal_bytes (void *buffer, size_t cnt,
+ bool (*in) (uint8_t *, void *aux), void *aux)
+{
+ uint8_t *p = buffer;
+ size_t i;
+
+ for (i = 0; i < cnt; i++)
+ if (!in (&p[i], aux))
+ return false;
+ return true;
+}
+
+enum backdoor_error
+backdoor_vunmarshal (const char *types, va_list args,
+ bool (*in) (uint8_t *, void *aux), void *aux)
+{
+ const char *p = types;
+
+ for (;;)
+ {
+ uint8_t c;
+
+ /* Find next type character. */
+ while (*p == ' ')
+ p++;
+ if (*p == '\0')
+ return BACKDOOR_OK;
+
+ /* Check type character in input. */
+ if (!in (&c, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ if (c != *p++)
+ return BACKDOOR_TYPE_MISMATCH;
+
+ switch (c)
+ {
+ case 's':
+ {
+ int32_t length;
+
+ if (!unmarshal_int32 (&length, in, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ if (length < 0)
+ return BACKDOOR_NEGATIVE_SIZE;
+ if (*p == '\'')
+ {
+ const char *end = strchr (++p, '\'');
+ if (length != end - p)
+ return BACKDOOR_STRING_MISMATCH;
+ while (p < end)
+ {
+ uint8_t q;
+ if (!in (&q, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ if (q != *p++)
+ return BACKDOOR_STRING_MISMATCH;
+ }
+ p++;
+ }
+ else
+ {
+ char *s = malloc (length + 1);
+ if (s == NULL)
+ return BACKDOOR_NOMEM;
+ if (!unmarshal_bytes (s, length, in, aux))
+ {
+ free (s);
+ return BACKDOOR_UNEXPECTED_EOF;
+ }
+ s[length] = '\0';
+ *va_arg (args, char **) = s;
+ }
+ }
+ break;
+
+ case 'i':
+ if (!unmarshal_int32 (va_arg (args, int32_t *), in, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ break;
+
+ case 'B':
+ {
+ int32_t size;
+ void *buffer;
+
+ if (!unmarshal_int32 (&size, in, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ if (size < 0)
+ return BACKDOOR_NEGATIVE_SIZE;
+ buffer = malloc (size);
+ if (size > 0 && buffer == NULL)
+ return BACKDOOR_NOMEM;
+ if (!unmarshal_bytes (buffer, size, in, aux))
+ {
+ free (buffer);
+ return BACKDOOR_UNEXPECTED_EOF;
+ }
+ *va_arg (args, size_t *) = size;
+ *va_arg (args, void **) = buffer;
+ }
+ break;
+
+ case 'b':
+ {
+ int32_t b;
+ if (!unmarshal_int32 (&b, in, aux))
+ return BACKDOOR_UNEXPECTED_EOF;
+ *va_arg (args, bool *) = b;
+ }
+ break;
+
+ default:
+ return BACKDOOR_BAD_TYPE;
+ }
+ }
+}
--- /dev/null
+#ifndef HEADER_BACKDOOR_H
+#define HEADER_BACKDOOR_H 1
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+enum backdoor_error
+ {
+ BACKDOOR_OK = 0,
+ BACKDOOR_NOMEM = -100,
+ BACKDOOR_BAD_TYPE,
+ BACKDOOR_TYPE_MISMATCH,
+ BACKDOOR_STRING_MISMATCH,
+ BACKDOOR_NEGATIVE_SIZE,
+ BACKDOOR_UNEXPECTED_EOF
+ };
+
+enum backdoor_error
+backdoor_vmarshal (const char *types, va_list args,
+ void (*) (uint8_t, void *aux), void *aux);
+enum backdoor_error
+backdoor_vunmarshal (const char *types, va_list args,
+ bool (*) (uint8_t *, void *aux), void *aux);
+
+#endif /* backdoor.h */